刚发现这种结构无法编译:
class A {
private int data;
public static int process(B b) {
return b.data;// error here: 'data has private access in A'
}
}
class B extends A {}
当然,这个问题可以通过手动轻松解决(将b转换为A,使场保护等)。但问题是,为什么java不允许这样的构造?我认为编译器必须知道B是A的子类,所以A的方法必须能够访问A的私有字段。
我能想到的唯一可能的问题是,如果B有自己的'数据'字段,编译器必须不知道我们想要访问哪个字段,但这就是继承的原因,对吧?
答案 0 :(得分:1)
好吧,编译器不允许它,因为语言规范不允许它。 JLS section 8.3(字段声明)指定(强调我的):
一个类继承自其直接超类,并直接超级接口超类和超接口的所有非私有字段,这些字段既可以访问类中的代码,也不会被类中的声明隐藏。
子类可以访问超类的私有字段 - 例如,如果两个类都是同一个类的成员。 然而,私有字段永远不会被子类继承。
因此,将该字段作为子类(6.5.6.2)的成员查找必须失败 - 编译器在解释失败的原因方面略有帮助,而不仅仅是说成员不存在,但我相信从纯粹的意义上说,查找应该只说“B类没有名为data
的成员”,而不是抱怨它无法访问。
至于为什么语言是这样设计的 - 我不确定。 C#中的等效代码很好,对我来说很有意义。例如,在C#5规范中,第3.4节:
当类型继承自基类时,基类的所有成员(实例构造函数,析构函数和静态构造函数除外)都将成为派生类型的成员。声明的基类成员可访问性不控制成员是否继承 - 继承扩展到任何不是实例构造函数,静态构造函数或析构函数的成员。但是,可能无法在派生类型中访问继承的成员,因为它声明了可访问性(第3.5.1节),或者因为它在类型本身(第3.7.1.2节)中被声明隐藏。