Page 556 - Introduction to Programming with Java: A Problem Solving Approach
P. 556
522 Chapter 13 Inheritance and Polymorphism
According to our dynamic binding discussion, the code would work just fine. The JVM would see a Dog object in the obj reference variable and bind the Dog’s display method to the obj.display method call. But it doesn’t matter that the code works fine in terms of dynamic binding. The code won’t compile successfully because the compiler senses there might be a problem.
When the compiler sees a method call, <reference-variable>.<method-name>(), it checks to see if the reference variable’s class contains a method definition for the called method. Note the obj.toString and obj.display method calls in the examples below. In the left example, the compiler checks to see if obj’s class, Object, contains a toString method. The Object class does contain a toString method, so the code compiles successfully. In the right example, the compiler checks to see if obj’s class, Object, contains a display method. The Object class does not contain a display method, so the code produces a compile-time error.
Object obj = new Dog();
Object obj = new Dog();
System.out.println(obj.toString()); obj.display();
legal
compile-time error
Wait a second! Does this mean that polymorphism works only for the methods defined in the Object class? Fortunately, that’s not the case. Later in this chapter, you’ll learn how to make polymorphism work for any method.
The instanceof Operator
Apago PDF Enhancer
As you’ve seen, whenever a generic reference calls a polymorphic method, the JVM uses the type of the ref- erenced object to decide which method to call. You might want to do a similar thing explicitly in your code. In particular, you might want to see if a referenced object is an instance of some particular class. You can do this with a special operator called the instanceof operator (note that the “o” in instanceof is lower- case). Using the Pets example again, suppose you want to print “Wags tail” if obj’s object is an instance of class Dog or any class descended from class Dog. You can do that with the if statement at the bottom of the main method in Figure 13.8. Thus, the instanceof operator provides a simple and direct way to sort out the various object types that might be referred to a by a generic reference variable.
13.6 Assignments Between Classes in a Class Hierarchy
Let’s now look at something that’s quite common with polymorphic programs—assigning an object to a reference where the object’s class and the reference’s class are different. In the following code fragment, as- sume that Student is a subclass of Person. What does this code fragment do?
Person p = new Student();
Student s = new Person();
Thisgeneratesacompile-timeerror.
The first line assigns a Student object (actually a reference to a Student object) to a Person reference variable. It’s assigning a subclass object to a superclass reference variable. That’s a legal assignment because a Student “is a” Person. It’s going up the inheritance hierarchy—the direction in which automatic type promotion occurs. The second line tries to assign a Person object to a Student reference variable. It’s trying to assign a superclass object to a subclass reference variable. That’s illegal because a Person is not necessarily a Student. The second line generates a compile-time error.