Reputation:
I know polymorphism happens in the case of method overriding. But I am a little confused about the below.
class A {
public void hi() {
System.out.println("A "+this.getClass().getName());
}
}
class B extends A {
public void bye() {
System.out.println("B "+this.getClass().getName());
}
}
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
A a = new B();
a.hi();
a.bye();
}
}
Output:
Main.java:35: error: cannot find symbol
a.bye();
^
symbol: method bye()
location: variable a of type A
1 error
Why does this give a compile time error?
In a = new B()
, the B
class object is created at runtime, so a
's a reference variable pointing to an object of type B
.
Now if we call B
's class method bye()
, why it is a compiler time error?
Upvotes: 2
Views: 3418
Reputation: 38910
You can access parent class methods only from parent class type.
A a = new B();
Solution 1:
Change parent to child ( B b = new B ()
) and call B methods.
Solution 2:
Check if parent is instance of Child object. If yes, cast the parent to Child and call the method.
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
A a = new B();
a.hi();
if ( a instanceof B){
((B)a).bye();
}
}
}
output:
A B
B B
Have a look at oracle documentation page on instanceof
The instanceof operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.
Upvotes: 0
Reputation: 12938
I think you have got the answer for your polymorphism problem from other answers. Addition to that, you can make your code work in this way with type casting.
(B)a.bye();
This is a good explanation for you to read about reference vs object types. And this is a good article about casting.
Upvotes: 0
Reputation: 636
An easy way to understand this is that A a might be actually pointing to the object of B, but during compile time the compiler doesn't know that.
The compiler only checks the reference i.e. 'a' and sees if its class , i.e. 'A' has the method that its reference 'a' is trying to call.
In your case, the reference 'a' does not have a method called bye() so according to the compiler such a call cannot be made and that is why you see that error.
Upvotes: 0
Reputation: 27692
Assigning the new B
instance to a reference of type A
is like making it wear the only-see-methods-defined-at-A glasses. That is you get the interface described at A
. And even though that instance has an implementation for bye
, you can only access hi
.
Upvotes: 0
Reputation: 691635
The declared type of the variable a
is A. The compiler doesn't know (and shouldn't know) what its concrete type at runtime is B. All it knows is that it's a A, and that there is no bye()
method in A.
The whole point of doing
A a = new B();
and not
B a = new B();
is to clearly say that a is a A, and could have any concrete type, as long as the conrete type extends A. You must be able, if you find a better implementation of A later, to just change that line to
A a = new BetterImplementation();
and have the code compile.
Upvotes: 2
Reputation: 393771
The a
variable may contain in run-time an instance of class A
or any sub-class of A
. Therefore, you can only call methods of class A
for that variable.
The compiler only cares about the compile-time type of the variable when it determines which method calls are valid.
Upvotes: 2