如果基类和派生类位于不同的程序包中,则不应继承来自 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类保护的)成员,“快速猜测”规则非常简单:
Base obj = new Base(); obj.baseProtectedMember();
编译)=>任何组合都可以使用(Base obj1 = new Derived2();
Derived2 obj2 = new Derived2(),依此类推-obj1.baseProtectedMember()
和obj2.baseProtectedMember()
是可见的,可以调用)。 我们不在乎其他类是什么包! Base obj = new Base(); obj.baseProtectedMember();
不编译)=>任何组合(请参见1)均无效。 我们不在乎其他类是什么包! 但是对于包私有成员,我们关心哪个层次结构类在哪个包中,并且我无法为一般情况制定一种简单可靠的“快速猜测”规则... < / p>
P.S。 有趣的旁注:
如果我在上面的代码段中(在文章顶部)覆盖Derived和DerivedFromDerived中的方法(将它们保留为程序包私有),则输出为:
f() from Base called
f() from Base called
答案 0 :(得分:1)
Base
和Driver
在同一包中,因此Driver
可以看到Base
的包私有方法。如果您将Base obj1 = new Derived()
声明为Derived obj1 = new Derived()
,则不会看到f()
。对于Base obj2 = new DerivedFromDerived()
也是一样,因为如果您将其声明为DerivedFromDerived
,则不会看到f()
。