Section 3.10 Object-Oriented Design: Inheritance and Polymorphism
This use of
toString() method provides our first look at Java's inheritance mechanism and how it promotes the generality and extensibility of the object-oriented approach. As a subclass of
OneRowNim class automatically inherits
toString() and any other
protected methods defined in
Object. We can simply use these methods as is, insofar as they are useful to us. As we saw in this case, the default version of
toString() wasn't very useful. In that case, we can override the method by defining a method in our class with the exact same method signature. The new version of
toString() can be customized to do exactly what is most appropriate for the subclass.
One of the great benefits of the object-oriented approach is the ability to define a task, such as
toString(), at a very high level in the class hierarchy and let the inheritance mechanism spread that task throughout the rest of the hierarchy. Because
toString() is defined in
Object, you can invoke this method for any Java object. Moreover, if you override
toString() in the classes you define, you will be contributing to its usefulness. Two important lessons from this example are
Principle 3.10.1. EFFECTIVE DESIGN: Inheritance.
The higher up in the class hierarchy that a method is defined, the more widespread its use can be.
Principle 3.10.2. EFFECTIVE DESIGN: Overriding
toString() method can be overridden in any user defined Java class. It is a useful thing to do in any class where the state of an object can be defined briefly.
Another important concept of object-oriented design is polymorphism. The
toString() method is an example of a polymorphic method. The term polymorphism is from the Greek terms poly, which means “many,” and morph, which means “form.” The
toString() method is polymorphic because it has different behavior when invoked on different objects.
For example, suppose we design a class,
Student, as a subclass of
Object and define its
toString() method to return the student ID number. Given this design, then
obj.toString() will return a student ID if
obj is an instance of
Student, but if it is an instance of
OneRowNim, it will return a the description of its state that we defined above. The following code segment illustrates this point:
Object obj; // obj can refer to any Object obj = new Student("12345");// obj refers to a Student System.out.println(obj.toString()); // Prints "12345" obj = new OneRowNim(11); // obj refers to a OneRowNim System.out.println(obj.toString()); // Prints: nSticks = 11, player = 1
In this case, the variable
obj is used to refer to a
Student and then to a
OneRowNim instance. This is okay because both classes are subclasses of
toString() is invoked on
obj, Java will figure out what subclass of
Object the instance belongs to and invoke the appropriate