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.
To put it simply, polymorphism in Java allows us to perform the same action in many different ways. Any Java object that can pass more than one IS-A test is polymorphic in Java. Therefore, all the Java objects are polymorphic as it has passed the IS-A test for their own type and for the class Object.
Polymorphism is considered one of the important features of Object-Oriented Programming. Polymorphism allows us to perform a single action in different ways. In other words, polymorphism allows you to define one interface and have multiple implementations.
Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object. Any Java object that can pass more than one IS-A test is considered to be polymorphic.
Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance. Like we specified in the previous chapter; Inheritance lets us inherit attributes and methods from another class. Polymorphism uses those methods to perform different tasks.
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.Java Language Specification - 9.6.4.4.
@Override
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.Java Language Specification - 8.8.7. Constructor Body
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
It's explained very well in the official docs:
https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
So, the Java compiler is adding super() without args for you.
In fact, if the class you are extending doesn't have a default constructor you will be required to call this constructor with args before.
Otherwise, the reason why AA:goo
is not being called is because is override by BB
even if it doesn't have the @Override
annotation, if you want to see that call you need to use super(); in your b:goo method. In fact, the foo is not override because it private so it's not possible to override it, if you try to add the annotation @Override you'll se you have a compilation failure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With