Java Reference
In-Depth Information
Java implements polymorphism through
dynamic binding
(also called
late binding
).
This means that the method to be executed is determined at run time during the
program execution.
Note that we can call the
toString
method on any object. Here is the reason.
In Java, we can invoke the
toString
method on any object. The reason is that
all classes inherit (directly or indirectly) from the
Object
class, which contains the
method
toString
as part of its public interface.
The
Object
class contains a default implementation of the
toString
method that simply
prints the address of the object (it actually prints a number that is associated with the
object because the address of the object can change during the execution, but this detail
is irrelevant to the programmer). This default behavior of the
toString
method can be
overridden in any class. Note that the
computeStrength
method is not defined in the
Object
class, which is the only superclass of the
FictionalCharacter
class. Therefore, we
have to define the method as an abstract method inside the
FictionalCharacter
class. If
the method is not defined inside the
FictionalCharacter
class, then the following code
will not compile.
FictionalCharacter tom;
...
System. out . println (tom. computeStrength() ) ;
The reason is that even though
tom
may actually point to an object that belongs to
a class that has the
computeStrength
method (e.g., the
Superhero
class), Java does not
know this at compile time and will not allow the program to compile.
As a last point in this section, we could have used the following code to print the
ArrayList characters
.
System. out . println ( characters ) ;
The reason is that the
ArrayList
class contains a
toString
method that prints the
ArrayList
. This method will be automatically called on the
ArrayList
. The method, in
turn, will call the
toString
method on each of the elements of the
ArrayList characters
.
However, we chose the previous syntax in order to explain how polymorphism works.
8.7 Interfaces and the
Comparable
Interface
Including the
computeStrength
method in the
FictionalCharacter
class is a valid
approach to allow the rest of the world to compare fictional characters. However, we seem
to be giving too much of our “secret sauce” away.
One rule of designing classes is that they should provide only the interface that
is needed by the outside world and should not provide any implementation-related
details. The reason is that these implementation-related details may change in the
future, but the interface of the class should remain constant.