代码之家  ›  专栏  ›  技术社区  ›  Jichao

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

  •  2
  • Jichao  · 技术社区  · 15 年前
    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()方法,它使(public方法)在用baseclass引用引用时不可见。由于对象dc引用的对象没有private void f()方法,或者因为派生类不能继承private方法,那么对象dc如何引用调用方法f()?

    谢谢。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Dilum Ranatunga    15 年前

    四点:

    (1)为了详细说明Vivyzer写了什么,代码编译是因为基类中的主方法可以访问类自己的私有方法。如果您将代码编写为:

    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

        2
  •  4
  •   TofuBeer    15 年前

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

    例如:

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

    有些人认为上面的代码不应该起作用,因为“a”是“私有的”。不是这样的,任何foo实例都可以访问任何其他foo实例的私有变量/方法。”private”只是指其他类(在本例中不是foo)的实例不能访问私有成员。

        3
  •  3
  •   James Keesey    15 年前

    为了保持事物的直线性,派生类(dc)确实继承了 private void f() 来自基类(BC)。这个继承的方法对DC不可访问,但它确实存在,因为在DC的BC部分调用的任何方法都必须访问所有BC。因此,当您将dc强制转换为bc时,继承的方法变得可用。现在,因为您在BC类内部运行代码,所以它可以访问BC的所有私有成员。如果您将main移到dc,它就不应该编译,更不用说运行了。

        4
  •  1
  •   vivyzer    15 年前

    主方法位于基类内部,私有方法对它可见。如果main在其他类中,它将不会编译。