我正在分解一个类以允许重用,不同的信息隐藏实现等。
它是:
public class Outer
{
public static class Inner
{
// ...
protected static void innerDoSomething()
{
// ...
}
}
public outerDoSomething()
{
//...
Inner.innerDoSomething();
//...
}
}
一切都很好,因为允许外部外部类访问嵌套的Inner类的受保护成员。
但试图分解如下:
public class SuperOuter
{
public static class SuperInner
{
// ...
protected static void innerDoSomething()
{
// ...
}
}
// ...
}
public class SubOuter extends SuperOuter
{
public static class SubInner extends SuperInner
{
// ...
protected static void innerDoSomethingElse()
{
// ...
}
}
public outerDoSomething()
{
//...
SubInner.innerDoSomethingElse(); // OK
SubInner.innerDoSomething(); // Error: cannnot access!
//...
}
}
即使SubInter可以访问SubInner的受保护成员,并且SuperInner的所有受保护成员都应该是SubInner受保护接口的一部分,也无法访问innerDoSomething()。
使其工作的唯一方法似乎是为每个方法添加显式委派,例如:
public static class SubInner extends SuperInner
{
// ...
protected static void innerDoSomethingElse()
{
// ...
}
protected static void innerDoSomething()
{
SuperInner.innerDoSomething();
}
}
这很烦人,容易出错并浪费时间。我很想将innerDoSomething()声明为public,但它并不正确,因为它只能由SubOuter及其子类使用。
怎么会?不应该通过SubOuter对innerDoSomething()受保护的访问进行ihnerited和accessibile吗?
受保护的方法无法通过变量引用从不同的包访问。如果两个类SuperOuter和SubOuter将在同一个包中,它将起作用。
好吧,我想我已经解决了这个问题,仔细阅读了Gosling的Java编程语言,第4版:
每个子类都继承超类的契约,并以某种方式扩展该契约。假设一个子类作为其扩展契约的一部分,对超类的受保护成员的值设置约束。如果不同的子类可以访问第一个子类的对象的受保护成员,那么它可以以破坏第一个子类的合同的方式操纵它们,这不应该是允许的。
因此,即使在我的情况下xxxInner逻辑上是xxxOuter的一部分,而SubOuter扩展SuperOuter所以前者在逻辑上应该能够访问后者的任何受保护成员,仍然SubOuter无法访问SuperOuter中受保护的SuperInner成员如果它已经接收到SuperInner作为参数的参数,那么它就不会这样,因为该参数可能属于完全不同的层次结构分支。在这种情况下,语言中没有特定的条款来建立连接。
这也解释了为什么显式委托有效:SubOuter可以访问SubInner的受保护成员,因为外部/嵌套授权,SubInner因为扩展而可以访问SuperInner的受保护成员,但是SubOuter无法访问SuperInner的受保护成员,因为后者实际上属于对于不同的层次结构分支,它是SubInner的工作来建立连接,所以说。
显式委托尊重上述内容,逻辑上和语言定义,所以它应该是“正确”的方式,考虑适当的访问,但由于冗余,它在实现中容易出错(如果我调用SuperInner.innerDoSomethingElse()怎么办?在SubInner.innerDoSomething()里面?)
最终:我可以使用一些python脚本来自动化显式委派,例如(我自动创建了具有类似冗余弱点的Builder模式),或者只是放弃了访问控制的附加安全性并使受保护的成员公开。