Java:为什么基类方法可以调用不存在的方法?

时间:2009-12-23 04:14:39

标签: java inheritance polymorphism

class BaseClass {
    private void f() {
        System.out.println("Baseclass f()");
    }

    public static void main(String[] args) {
        BaseClass dc = new DerivedClass();
        dc.f();
    }
}

class DerivedClass extends BaseClass {
    public void f() {
        System.out.println("DerivedClass f()");
    }
}

在我看来,对象dc指的是应该只有一个非覆盖方法 - public void f()方法,这使得它(公共方法)在引用BaseClass引用时不可见。由于对象dc referes没有私有void f()方法,因为DeriverClass无法继承私有方法,对象dc如何引用调用方法f()?

感谢。

4 个答案:

答案 0 :(得分:4)

一个常见的(ish)误解是私有是每个实例而不是每个类。

例如:

class Foo
{
    private int a;

    public bar(final Foo other)
    {
        other.a = 5;
    }
}

有些人认为上面的代码不起作用,因为“a”是“私有的”。情况并非如此,任何Foo实例都可以访问任何其他Foo实例的私有变量/方法。 “private”只是意味着其他类的实例(在这种情况下不是Foo)无法访问私有成员。

答案 1 :(得分:3)

为了保持正确,DerivedClass(DC)DOES从BaseClass(BC)继承private void f()。 DC无法访问此继承的方法,但它存在,因为在DC的BC部分中调用的任何方法都必须能够访问所有BC。因此,当您将DC转换为BC时,继承的方法变为可用。现在因为你在BC类中运行代码,它可以访问BC的所有私有成员。如果你将main移动到DC,它就不应该编译,更不用说运行了。

答案 2 :(得分:1)

主要方法在BaseClass中,私有方法对它可见。如果main在某个其他类中,它将无法编译。

答案 3 :(得分:1)

四点:

(1)为了详细说明vivyzer所写的内容,代码进行编译,因为BaseClass中的main方法可以访问类自己的私有方法。如果您将代码编写为:

class BaseClass {
  private void f() { }
}

class DerivedClass {
  public void f() { }
}

class Bystander {
  public static void main() {
    BaseClass inst = new DerivedClass();
    inst.f();
  }
}

然后代码无法编译。

(2)语言允许这种情况支持基类的作者可以添加新的私有方法而不必担心其他作者的派生类型的用例。

(3)如果方法不是私有的,你不会看到这个。如果基类的f()具有包或受保护的可见性,则该方法将是虚方法。

(4)Java不支持#2的反向。具体来说,如果派生类具有私有方法,并且新版本的基本类型引入了具有相同签名的非私有方法,则派生类和新基类不能一起使用。还有其他语言(例如C#)可以更完整地解决这些类型的模块化,代际开发问题。如果您对这方面感兴趣,可以阅读Artima:Versioning, Virtual, and Override