我有三节课。
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?
答案 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