复杂继承/包组合中的包私有成员可见性-Qiuck General Rule验证可见性

时间:2019-01-05 20:58:37

标签: java inheritance visibility protected package-private

如果基类和派生类位于不同的程序包中,则不应继承来自 Base package-private成员,因此在 Derived 中不存在em>,即通过Base obj = new Derived()Derived obj = new Derived()-obj.member()都无法访问该成员,无论哪种情况都将产生编译错误!

但是我发现Base obj = new Derived()可以访问obj.f()

是的,私有成员仍然存在,因为当我创建new Derived()时,new Base()也会与其所有私有成员一起创建(在幕后)。但是,如果我将下面代码中的 package-private f()更改为 private ,则obj.f()将会像预期的那样Base obj = new Derived()的编译错误... 无论如何,我怀疑在我的具有包私有成员的示例中,情况完全是这样-可以从派生类访问其隐含类(基类)的私有成员(-)(隐式存在)。 / em>

(-)(因为Base和Derived在不同的程序包中)

package com.main_pkg;

public class Base {     
    void f() { } // default visibility        
}

package org.another_pkg;

import com.main_pkg.Base;

public class Derived extends Base {         

}

package com.totally.different_pkg;

import org.another_pkg.Derived;

public class DerivedFromDerived extends Derived {

}

最终

import org.another_pkg.Derived;

import com.totally.different_pkg.DerivedFromDerived;

public class Driver {  // Base class is in same pkg as Driver!

    public static void main(String[] args) {
        Base obj1 = new Derived();
        obj1.f(); // f() is visible!

        Base obj2 = new DerivedFromDerived();
        obj2.f();  // f() is visible!
    }
}

您能否制定一条便捷的实用规则(换句话说,除了在JLS和通用的默认可见性定义中),如何理解复杂的可见性(访问)继承/包组合((我们可能具有复杂的层次结构Base-> Derived-> Derived2-> Derived3,并且每个类都可以位于相同/不同的包中。如何快速查询可访问性?

例如,对于(受Base类保护的)成员,“快速猜测”规则非常简单:

  1. 如果 Base和Driver位于同一软件包中(即来自任何Driver的 方法代码Base obj = new Base(); obj.baseProtectedMember(); 编译)=>任何组合都可以使用(Base obj1 = new Derived2(); Derived2 obj2 = new Derived2(),依此类推-obj1.baseProtectedMember()obj2.baseProtectedMember()是可见的,可以调用)。 我们不在乎其他类是什么包!
  2. 如果Base和Driver不在同一包中(即来自任何Driver的     方法代码Base obj = new Base(); obj.baseProtectedMember();     不编译)=>任何组合(请参见1)均无效。 我们不在乎其他类是什么包!

但是对于包私有成员,我们关心哪个层次结构类在哪个包中,并且我无法为一般情况制定一种简单可靠的“快速猜测”规则... < / p>

P.S。 有趣的旁注:

如果我在上面的代码段中(在文章顶部)覆盖Derived和DerivedFromDerived中的方法(将它们保留为程序包私有),则输出为:

f() from Base called
f() from Base called

1 个答案:

答案 0 :(得分:1)

BaseDriver在同一包中,因此Driver可以看到Base的包私有方法。如果您将Base obj1 = new Derived()声明为Derived obj1 = new Derived(),则不会看到f()。对于Base obj2 = new DerivedFromDerived()也是一样,因为如果您将其声明为DerivedFromDerived,则不会看到f()