是否可以在超类对象上调用子类的方法?

16 java inheritance subclass superclass

动物是狗和狗的超类有一种叫做树皮的方法

public void bark()
{
    System.out.println("woof");
}
Run Code Online (Sandbox Code Playgroud)

考虑以下:

Animal a = new Dog();
if (a instanceof Dog){
    a.bark();
}
Run Code Online (Sandbox Code Playgroud)

会发生什么?

  1. 不允许转让
  2. 允许对树皮的调用,并在运行时打印"woof"
  3. 允许吠叫,但没有打印
  4. 对bark的调用会导致编译时错误
  5. 对bark的调用导致运行时错误

当我们检查对象是否是狗时,我说2; 因为狗是带有树皮方法的类,如果是,那么我们称它为打印出来的:s

我的理解在这里是否正确?

Sam*_*ost 32

这将无法编译,因为Animal没有名为bark的方法.想一想,所有的狗都是动物,但不是所有的动物都是狗.所有的狗都吠叫,但不是所有的动物都吠


sim*_*622 27

不 - 答案是;

4)对bark的调用导致编译时错误

bark方法没有被定义为赋值类型Animal的方法,因此会导致编译时间问题; 这可以通过铸造来解决;

((Dog)a).bark();
Run Code Online (Sandbox Code Playgroud)


coo*_*ird 11

关键在于以下行:

Animal a = new Dog();
Run Code Online (Sandbox Code Playgroud)

虽然Dog创建了一个新实例,但它的引用a是声明属于该类型的引用Animal.因此,任何引用a都会new Dog被视为一个Animal.

因此,除非Animalbark方法,否则以下行将导致编译器错误:

a.bark();
Run Code Online (Sandbox Code Playgroud)

即使a经过测试以查看它是否是实例Dog并且a instanceof Dog实际将返回true,该变量a仍然是类型的Animal,因此if语句中的块仍然处理aAnimal.

这是静态类型语言的一个特性,其中变量被提前分配一个类型,并在编译时检查以查看类型是否匹配.如果此代码是在动态类型语言上执行的,那么在运行时检查类型,可以允许以下类似的内容:

var a = new Dog();
if (a instanceof Dog)
    a.bark();
Run Code Online (Sandbox Code Playgroud)

a.bark()保证仅在实例为a时执行Dog,因此调用bark始终有效.但是,Java是一种静态类型的语言,因此不允许使用这种类型的代码.


Bil*_*ard 5

Head First Java中,他们使用电视遥控器的非常好的类比作为参考,并将电视作为参考指向的对象.如果您的遥控器只有按钮(方法),开启,关闭,频道上下,以及音量增大和减小,那么电视的酷炫功能并不重要.您仍然只能从遥控器上执行这些基本操作.例如,如果遥控器没有静音按钮,则无法将电视静音.

Animal参考只知道动物方法.底层对象具有哪些其他方法并不重要,您无法从Animal引用访问它们.