关于超类引用和子类对象的混淆

时间:2012-05-08 05:12:18

标签: java inheritance reference modifier method-overriding

我对此代码有一些疑问:

class superclass
{
    void bark() {}
}

class subclass extends superclass
{
    void bark() {}

    public static void main(String[] args) {
        superclass refvar = new subclass();
        refvar.bark();
    }
}
  1. 为什么父母在这种情况下有一个方法,孩子是否有这种方法?我被告知在编译时引用变量是超类类型,因此编译器在编译时在超类中检查此方法;这是准确的吗?

  2. 当编译器读取bark()时,它如何知道接下来要去哪里?我知道子方法会覆盖它,但我想知道它首先进入超类方法或子类,以及为什么。

  3. 为什么子类需要具有更广范围的访问修饰符?

2 个答案:

答案 0 :(得分:1)

  1. refvar被声明为superclass对象,这就是bark()必须在superclass中声明refvar.bark()才能编译的原因。< / p>

  2. 它查找实例对象的bark()实现。

  3. 将某些内容覆盖到较窄范围内没有多大意义。

答案 1 :(得分:1)

  

为什么父母在这种情况下需要一个方法,   孩子是否有这种感觉?

您的示例在静态类型为bark()的对象上调用superclass - 如果superclass未声明方法bark(),则编译器不会知道这个将是一个有效的电话。

  

我被告知在编译时   引用变量是超类类型,因此编译器会检查   这个方法在编译时的超类中;这是准确的吗?

是的,实际上这与我上面所说的一致。

  

当编译器读取bark()时,它如何知道接下来要去哪里?一世   知道子方法会覆盖它,但我想知道它的第一个   转到超类方法或子类,以及原因。

实际上,编译器接下来不会去任何地方。在编译时重要的是bark()是对superclass类型的对象的有效调用。只有在运行时才会将调用分派到bark()中声明的subclass覆盖。

  

为什么子类需要具有更宽范围的访问修饰符?

我假设你的意思是子类的重写方法。为了澄清,它必须具有相等或更广泛的访问权限。它不能具有较窄访问权限的原因是因为这会破坏超类定义的契约。

例如,如果您被允许在bark()中将private更改为subclass,那么理论上对该方法的调用不应在subclass之外工作。但它需要工作,因为superclass没有使bark()私有:

class ClassInTheSamePackageAsTheOtherTwo {

    public static void main(String[] args) {
        superclass refvar = new subclass();
        refvar.bark(); //as far as the compiler knows, this call is valid
    }
}