I'm studying CS and we have questions about polymorphism that I cant wrap my mind around. Here is an example:
public class AA{
public AA(){
foo();
}
private void foo() {
System.out.print("AA::foo ");
goo();
}
public void goo(){
System.out.print("AA::goo ");
}
}
public class BB extends AA{
public BB(){
foo();
}
public void foo(){
System.out.print("BB:foo ");
}
public void goo(){
System.out.print("BB::goo ");
}
public static void main(String[] args){
// Code goes here
}
}
When in void main i add the line:
AA a = new BB();
it goes first AA constructor prints AA:foo but then goo() sends it to BB's goo, why so?
Simple polymorphism such as "Animal -> cat/spider/dog" is easy to understand but when it comes to this I'm just lost. Can you guys give me any tips how to read this code? What are the rules are?
EDIT: there is no @Override
annotation because this is a question from an exam.
Explanation
public class AA {
private void foo() { ... }
^^^^^^^
}
Polymorphism is not applied to private
methods. A subclass does not inherit private
methods, so they cannot be overridden:
A class
C
inherits from its direct superclass all concrete methodsm
(both static and instance) of the superclass for which all of the following are true:
m
is a member of the direct superclass ofC
.m
ispublic
,protected
, or declared with package access in the same package asC
.- No method declared in
C
has a signature that is a subsignature of the signature ofm
.Java Language Specification - 8.4.8. Inheritance, Overriding, and Hiding
Therefore, the foo()
call from the A
constructor doesn't invoke BB#foo
, it calls AA#foo
.
But the goo()
call within AA#foo
refers to the overridden method BB#goo
. Here, with public
methods, method overriding and polymorphism were applied.
It's a bit tricky, so I would recommend you put the @Override
annotation everywhere it's supposed to be.
public class BB extends AA {
@Override // it doesn't compile - no overriding here
public void foo() { ... }
@Override // it does override
public void goo() { ... }
}
It also might be helpful to detect another problem:
Programmers occasionally overload a method declaration when they mean to override it, leading to subtle problems. The annotation type
Override
supports early detection of such problems.If a method declaration in type
T
is annotated with@Override
, but the method does not override fromT
a method declared in a supertype ofT
, or is not override-equivalent to a public method ofObject
, then a compile-time error occurs.
Illustration
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class
Object
, then the constructor body implicitly begins with a superclass constructor invocationsuper();
, an invocation of the constructor of its direct superclass that takes no arguments.
To put it simply,
public BB() {
foo();
}
turns into
public BB() {
super();
foo();
}
Keeping super();
in mind, we can make the next illustration:
new BB()
AA() // super(); -> AA constructor
A#foo() // private method call
B#goo() // polymorphic method call
BB() // BB constructor
B#foo() // plain method call