Java:无法在外部类的子类中访问嵌套类子类的受保护方法

问题描述 投票:0回答:2

我正在分解一个类以允许重用,不同的信息隐藏实现等。

它是:

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吗?

java inner-classes protected
2个回答
1
投票

受保护的方法无法通过变量引用从不同的包访问。如果两个类SuperOuter和SubOuter将在同一个包中,它将起作用。


0
投票

好吧,我想我已经解决了这个问题,仔细阅读了Gosling的Java编程语言,第4版:

  1. SuperOuter和SubOuter在逻辑上应该是不同的包装,因此没有毯子整包保护成员可访问性。
  2. 对嵌套类的受保护成员的访问实际上是作为外部类和嵌套类之间的特殊访问方式(参见第5章。嵌套类和接口)
  3. 然而,受保护的成员可访问性不仅仅是传递性的:除了嵌套/外部授权之外,您需要两者都在子类中并且具有至少属于该子类的类型的引用(即,至少SubXXX,SuperXXX是不够的),因为,我引用第3.5段。什么保护真的意味着:

每个子类都继承超类的契约,并以某种方式扩展该契约。假设一个子类作为其扩展契约的一部分,对超类的受保护成员的值设置约束。如果不同的子类可以访问第一个子类的对象的受保护成员,那么它可以以破坏第一个子类的合同的方式操纵它们,这不应该是允许的。

因此,即使在我的情况下xxxInner逻辑上是xxxOuter的一部分,而SubOuter扩展SuperOuter所以前者在逻辑上应该能够访问后者的任何受保护成员,仍然SubOuter无法访问SuperOuter中受保护的SuperInner成员如果它已经接收到SuperInner作为参数的参数,那么它就不会这样,因为该参数可能属于完全不同的层次结构分支。在这种情况下,语言中没有特定的条款来建立连接。

这也解释了为什么显式委托有效:SubOuter可以访问SubInner的受保护成员,因为外部/嵌套授权,SubInner因为扩展而可以访问SuperInner的受保护成员,但是SubOuter无法访问SuperInner的受保护成员,因为后者实际上属于对于不同的层次结构分支,它是SubInner的工作来建立连接,所以说。

显式委托尊重上述内容,逻辑上和语言定义,所以它应该是“正确”的方式,考虑适当的访问,但由于冗余,它在实现中容易出错(如果我调用SuperInner.innerDoSomethingElse()怎么办?在SubInner.innerDoSomething()里面?)

最终:我可以使用一些python脚本来自动化显式委派,例如(我自动创建了具有类似冗余弱点的Builder模式),或者只是放弃了访问控制的附加安全性并使受保护的成员公开。

© www.soinside.com 2019 - 2024. All rights reserved.