[英]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.