简体   繁体   中英

Why can't subclass see method of parent class?

I have three classes.

Class A

public class A {

}

Class B

public class B extends A {

    public void hello(){
        System.out.println("hello");
    }
}

Class C

public class C extends B {

}

Class Test

public class Test {

    public static void main(String[] args) {
        A a = new C();
        a.hello(); // The method hello() is undefined for type A
    }
}

The code above will not compile because it reports an error that reads "The method hello() is undefined for type A"

My question is, since "a" is a C object, why doesn't a.hello() use the hello() method in the parent class of B ?

If I add a hello method to A class, only then does the code above use the hello() from B class, but why do I have to add hello() to A class in order to use the method from B class?

A is a top level class in your hierarchy. It sees only those methods that are defined within it. Methods defined by its subclasses are not accessible to A . Sure, you can assign C to variable A , and then you can use it wherever A can be used, but now C will be limited to methods that A has.

It makes sense when you think about it. When you define a type ( A ), you expect it to behave according to your definition (which does not include anything about C fields and methods). You do not expect it to suddenly have everything that subclasses might have defined (eg, imagine situation where a hundred people extended your class in various ways - top class would become incredibly bloated and broad).

That is why subclasses extend parent classes - they add additional functionality that is not (and probably should not be) defined in its parent. However, the parent itself has no awareness of the additional functionality and cannot use it. Each class can only use what it has defined or its parent(s) has defined. Hence, when you assign C to the parent's type, you will only get those methods that A is aware of (but with C 's implementation).

Consider:

public class Animal {
    public void walk() {
        System.out.println("Walking");
    }
}


public class Dog extends Animal {
    public void bark() {
        System.out.println("Woof");
    }

    @Override
    public void walk() {
        System.out.println("Doggy walk");
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        Animal animal = new Animal();
        Animal animalDog = new Dog();
        dog.walk(); // "Doggy walk"
        dog.bark(); // "Woof"
        animal.walk(); // "Walking"
        animal.bark(); // Error: bark() is not defined in the Animal class
        animalDog.walk(); // "Doggy walk"
        animalDog.bark(); // Error: Animal class has no bark()
    }
}

Since we assigned Dog to Animal type, it can only use methods that are defined in Animal class. But note that the behavior will be the one that you defined in Dog class for the same method.

If you must use the method and for some reason you have not assigned it to a type that has the method, you should cast it accordingly, eg:

((Dog) animalDog).bark(); // "Woof"

When you define a as an A type object ( A a = new C(); ), it only has access to the members and methods of type A . To do what you want, either define hello() on type A or define a as an object of type B ( B a = new C(); ). This is because the compiler is keeping track of which methods it has available. If, for some reason, you don't actually have access to the instantiation but you need to access something from B but it's handed to you as an A object, then you can cast it:

if (a instanceof B) (B a).hello();
else throw new Exception();

It's all about variable types. You are instantiating C class, but treat result object as A. Interface of A class does not contain 'hello' method, that's why you can't use it in your example.

To solve the problem you should either add your method to A or update type of the variable to B.

当您将变量声明为具有超类的类型时,您只能通过该变量访问(公共)方法和超类的成员变量。

In your question A is a parent class of B ,B is the parent class of C (ie A->B->C) and you create the object of C class through A . So, according to your program firstly it try to find the hello() method in A class because it is a super parent class of C, which is not defined hello() method that's why it shows an error.

I think you're a bit confused on how polymorphism works. You're saying "a" is a "c" object, which is a misleading assumption that many beginners make. So here's an example to illustrate what's happening:

Say you have an "Animal" class, which is extended by a separate "Dog" class, because a Dog is an Animal. So we can write:

Animal someAnimal = new Dog();

The above statement can be rewritten as:

Dog someDog = new Dog();
Animal someAnimal = someDog;

which shows that a Dog object can be stored as an Animal object. Why? Because a Dog is an Animal. You can't do

Dog someDog = new Animal();

because an Animal is not [necessarily] a Dog.

This points back to your original assertion. Your "a" is not a "c" object because you never wrote something like:

C a = new A(); // sidenote : this will give you error, as you are saying the analogous Animal is a Dog

As a result, your superclass (which is "A") can not access methods from the subclass (which in this case is "B") because superclasses don't inherit from subclasses (it's the other way round).

在方法重写中,您应该在超类中具有相同的方法。在这种情况下,大多数超类是A

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