In Java, Dog extends Animal and overrides speak(). Animal's speak() returns "..." and Dog's returns "Woof". What does this code print?
Animal a = new Dog();
System.out.println(a.speak());
A...
BWoof
CNothing, because the code does not compile
DBoth "..." and "Woof"
The variable a has declared type Animal, but the object it refers to is a Dog. Java chooses an overridden instance method by the object's run-time type, so Dog's speak() runs and prints Woof. This is dynamic dispatch.
Question 2 Multiple Choice
Continuing the example, Dog also defines a method fetch() that Animal does not have. What happens with this Java code?
Animal a = new Dog();
a.fetch();
AIt runs Dog's fetch(), because the object is a Dog
BIt runs Animal's fetch(), because the variable is an Animal
CIt causes a compile-time error, because Animal has no fetch() method
DIt compiles but always throws an exception at run time
The compiler checks method calls against the declared type of the variable. Animal has no fetch(), so the call is rejected before the program runs. The run-time type decides which version of a method runs only after the compiler has accepted the call. A cast, ((Dog) a).fetch(), would compile.
Question 3 True / False
Writing two methods named area in the same class, one taking (double r) and one taking (double w, double h), is an example of overriding.
TTrue
FFalse
Answer: False
Same name with different parameter lists in one class is overloading, and the compiler picks the version from the argument types. Overriding is a subclass redefining an inherited method with the same name and parameters.
Question 4 Short Answer
A program stores Circle, Square and Triangle objects in one list of type Shape and computes the total area with a single loop that calls shape.area(). Explain why the loop needs no if-statements to check each object's type.
Think about your answer, then reveal below.
Model answer: Each subclass overrides area(). When the loop calls shape.area(), dynamic dispatch runs the version that belongs to the object's actual class, so each shape computes its own area. A new subclass such as Hexagon will work in the same loop without changing it.
This is the practical value of polymorphism: code written against the superclass works for every subclass, including ones written later, because method choice happens at run time.