简体   繁体   English

为什么子类看不到父类的方法?

[英]Why can't subclass see method of parent class?

I have three classes. 我有三节课。

Class A A级

public class A {

}

Class B B级

public class B extends A {

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

Class C 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" 上面的代码将无法编译,因为它报告一个错误,内容为“方法A类型的hello()未定义”

My question is, since "a" is a C object, why doesn't a.hello() use the hello() method in the parent class of B ? 我的问题是,由于“ a”是C对象,为什么a.hello()B的父类中不使用hello()方法?

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类添加hello方法,则只有上面的代码才使用B类中的hello() ,但是为什么我必须向A类中添加hello()才能使用B类中的方法?

A is a top level class in your hierarchy. A是层次结构中的顶级类。 It sees only those methods that are defined within it. 它仅查看其中定义的那些方法。 Methods defined by its subclasses are not accessible to A . 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. 当然,您可以将C分配给变量A ,然后可以在可以使用A任何地方使用它,但是现在C将限于A拥有的方法。

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). 定义类型( A )时,您希望它的行为符合您的定义(其中不包括有关C字段和方法的任何内容)。 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). 因此,当您将C分配给父类的类型时,只会获得A知道的那些方法(但使用C的实现)。

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. 由于我们将Dog分配为Animal类型,因此只能使用Animal类中定义的方法。 But note that the behavior will be the one that you defined in Dog class for the same method. 但是请注意,该行为将是您在Dog类中为同一方法定义的行为。

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 . 当将a定义为A类型对象( A a = new C(); )时,它只能访问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(); ). 要执行所需的操作,请在类型A上定义hello()或将a定义为类型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: 如果由于某种原因您实际上没有访问实例化的权限,但是您需要访问B某些内容,但是将其作为A对象传递给您,则可以进行强制转换:

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. 您正在实例化C类,但将结果对象视为A。A类的接口不包含“ hello”方法,这就是为什么您不能在示例中使用它的原因。

To solve the problem you should either add your method to A or update type of the variable to B. 要解决该问题,您应该将方法添加到A或将变量的类型更新为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 . 在您的问题中A是B的父类,B是C的父类(即A-> B-> C),并且您通过A创建C类的对象。 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. 因此,首先根据您的程序,它尝试在A类中找到hello()方法,因为它是C的超父类,未定义hello()方法,这就是它显示错误的原因。

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. 您是说“ a”是“ c”对象,这是许多初学者所做的误导性假设。 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. 这表明Dog对象可以存储为Animal对象。 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: 您的“ a”不是“ c”对象,因为您从未写过以下内容:

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”)无法访问子类(在本例中为“ B”)中的方法,因为超类不继承自子类(反之亦然)。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能将父类分配给子类类型的变量? - Why can't I assign a parent class to a variable of subclass type? 为什么父类class会调用java中的子类方法? - Why the parent class will call the subclass method in java? 抽象类的子类无法看到构造函数 - Subclass of abstract class can't see constructor 为什么我不能使用引用子类型实例的父类型的引用来调用子类方法? - why can't I call a subclass method using a reference of a parent type that refers to an instance of a sub-type? 为什么方法不能采用Collection <subClass> 当方法的签名定义为Collection时 <class> - Why can't a method take a Collection<subClass> when the method's signature is defined as Collection<class> 为什么不能在同一个包中调用另一个类的包私有方法呢? - Why can't I call a package-private method of another class that's a subclass of a class in the same package? 子类可以强制对父类方法的调用是编译器错误吗? - Can a subclass force a call to a parent class method to be a compiler error? 在另一个函数中创建子类的实例时,为什么不能从子类类型的 Abstact 类调用方法(公共或静态)? - Why can't I call a method (public or static) from an Abstact class of type subclass when creating an instance of the subclass in another function? 超级 class 方法的 Inheritance 方法无法获取子类中的详细信息? - Inheritance method of super class method can't get the details in subclass? 为什么我们不能在 java 的子 class 的方法之外访问 class 内部的父实例变量 class? - why can't we access parent class instance variables inside the class outside the method in child class in java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM