简体   繁体   中英

Why do I get a compile-time error when calling a subclass method using superclass reference?

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 'sa 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?

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.

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.

Polymorphism is basically the ability of an object to take many forms. Since your parent class is referring to the subclass object, it is polymorphism.

Main.java:35: error: cannot find symbol
        a.bye();
         ^
  symbol:   method bye()
  location: variable a of type A
1 error

You are getting this error because you are trying to call a method of subclass from superclass reference.

Here you are assigning subClass object ref to superclass which is fine. But superclass can only call it's own known methods and data.

A a = new B();
 a.hi(); // member of super class
 a.bye(); // Not a member a super class

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 .

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 ie 'a' and sees if its class , ie '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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM