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

时间:2017-05-30 04:46:44

标签: java inheritance

我有三节课。

A类

public class B extends A {

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

B类

public class C extends B {

}

C类

public class Test {

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

班级考试

C

上面的代码无法编译,因为它报告的错误是"方法hello()未定义类型A"

我的问题是,因为" a"是一个a.hello()对象,为什么hello()使用B父类中的A方法?

如果我向hello()类添加一个hello方法,那么上面的代码才会使用B类中的hello(),但为什么我必须将A添加到B }},以便使用Public Function Volume(x As Double, xmax As Double, Flows As Range) As Double() Dim lCt As Long Dim Y4(1 To 10, 1 To 1) As Double 'A bunch of stuff which eventually fills Y4 For lCt = 1 To 10 Y4(lCt, 1) = Rnd() Next Volume = Y4 End Function class?

中的方法

7 个答案:

答案 0 :(得分:2)

A是层次结构中的顶级类。它只能看到在其中定义的那些方法。 A无法访问由其子类定义的方法。当然,您可以将C分配给变量A,然后您可以在A可以使用的任何地方使用它,但现在C将仅限于{{1}的方法}} 具有。

当你想到它时,这是有道理的。定义类型(A)时,您希望它根据您的定义(不包含A字段和方法的任何内容)来表现。你不要指望它突然拥有子类可能定义的所有东西(例如,想象一下百人以各种方式扩展你的课程的情况 - 顶级课程会变得非常臃肿和宽泛)。

这就是子类扩展父类的原因 - 它们添加了在其父级中未定义(也可能不应该)的其他功能。但是,父级本身并不了解其他功能,也无法使用它。每个类只能使用它定义的内容或其父代定义的内容。因此,当您将C分配给父类型时,您将只获得C知道的方法(但A的实现方式)。

考虑:

C

由于我们已将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() } } 分配给Dog类型,因此它只能使用Animal类中定义的方法。但请注意,行为将是您在Animal类中为同一方法定义的行为。

如果您必须使用该方法,并且由于某种原因您尚未将其分配给具有该方法的类型,则应相应地进行转换,例如:

Dog

答案 1 :(得分:1)

当您将a定义为A类型对象(A a = new C();)时,它只能访问A类型的成员和方法。要执行您想要的操作,请在类型hello()上定义A或将a定义为B类型的对象(B a = new C();)。这是因为编译器正在跟踪它可用的方法。如果由于某种原因,您实际上无法访问实例化但是您需要访问B中的某些内容但它已作为A对象传递给您,那么您可以将其强制转换为:

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

答案 2 :(得分:1)

所有关于变量类型。您正在实例化C类,但将结果对象视为A.类的接口不包含'hello'方法,这就是您不能在示例中使用它的原因。

要解决此问题,您应该将方法添加到A或将变量类型更新为B.

答案 3 :(得分:1)

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

答案 4 :(得分:1)

在你的问题中,A是B的父类,B是C的父类 (即A-> B-> C)并且您通过A创建C类的对象。所以,根据你的程序首先尝试在A类中找到hello()方法,因为它是C的超级父类,没有定义hello()方法,这就是它显示错误的原因。

答案 5 :(得分:1)

我认为你对多态性如何运作有点困惑。你在说" a"是一个" c"对象,这是许多初学者所做的误导性假设。所以这里举例说明发生了什么:

假设你有一个动物"课程,由一个单独的" Dog"上课,因为狗是动物。所以我们可以写:

Animal someAnimal = new Dog();

以上陈述可以改写为:

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

表示Dog对象可以存储为Animal对象。为什么?因为狗是动物。你无法做到

Dog someDog = new Animal();

因为动物不一定是狗。

这回到你原来的断言。你的" a"不是" c"对象,因为你从未写过类似的东西:

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

结果,你的超类(" A")无法访问子类中的方法(在这种情况下是" B")因为超类不是继承自子类(反过来说)。

答案 6 :(得分:0)

在方法覆盖中,你应该在超类中使用相同的方法。在这种情况下,大多数超类是A