Java: 无法访问外部 class 的 subclass 中嵌套 class subclass 的受保护方法

Java: Cannot access protected methods of nested class subclass in subclass of outer class

我正在分解 class 以允许重用、不同的信息隐藏实现等

是:

public class Outer
{
    public static class Inner
    {
        // ...
        protected static void innerDoSomething()
        {
            // ...
        }
    }

    public outerDoSomething()
    {
        //...   
        Inner.innerDoSomething();
        //...
    }
}

一切都很好,因为外部 Outer class 被允许访问嵌套 Inner class.

的受保护成员

但试图这样分解:

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!
        //...
    }
}

innerDoSomething() 不可访问,即使 SubInner 的受保护成员可以被 SubOuter 访问,并且 SuperInner 的所有受保护成员都应该是 SubInner 受保护接口的一部分。

让它工作的唯一方法,似乎是为每个方法添加显式委托,例如:

    public static class SubInner extends SuperInner
    {
        // ...
        protected static void innerDoSomethingElse()
        {
            // ...
        }

        protected static void innerDoSomething()
        {
            SuperInner.innerDoSomething();
        }
    }

这很烦人、容易出错并且浪费时间。我很想将 innerDoSomething() 声明为 public,但这并不正确,因为它只能由 SubOuter 及其 subclasses 使用。

怎么会? innerDoSomething() 受保护的访问不应该被 SubOuter 授予和访问吗?

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

好的,我想我绕过了它,仔细重读了 Gosling 的 Java 编程语言,第 4 版:

  1. SuperOuter 和 SubOuter 在不同的包中,从逻辑上讲,它们应该在不同的包中,因此 没有全面包 受保护的成员可访问性。

  2. 访问嵌套 class 的受保护成员实际上是作为外部和嵌套 classes[=41= 之间的特殊访问方式](参见第 5 章嵌套 类 和接口

  3. 然而,受保护的成员可访问性不是简单的传递:除了形式nested/outer授予,你需要两者都在子class 并有一个至少是那个 subclass 类型的引用(即至少 SubXXX,SuperXXX 是不够的),因为,我引用段落 3.5。受保护的真正含义

Each subclass inherits the contract of the superclass and expands that contract in some way. Suppose that one subclass, as part of its expanded contract, places constraints on the values of protected members of the superclass. If a different subclass could access the protected members of objects of the first subclass then it could manipulate them in a way that would break the first subclass's contract and this should not be permissible.

因此,即使在我的例子中 xxxInner 在逻辑上是 xxxOuter 的一部分,并且 SubOuter 扩展了 SuperOuter 因此前者在逻辑上应该能够访问后者的任何受保护成员,但 SubOuter 仍然无法访问 SuperInner 的受保护成员在 SuperOuter 中,如果它收到一个 SuperInner 作为参数的参数,它就不能以相同的方式,因为该参数可能属于完全不同的层次结构分支。在这种情况下,语言中没有具体规定来建立联系。

这也解释了为什么显式委托有效:SubOuter 可以访问 SubInner 的受保护成员,因为 outer/nested grant,而 SubInner 可以访问 SuperInner 的受保护成员,因为扩展,但是 SubOuter 不能访问 SuperInner 的受保护成员SuperInner,因为后者实际上可能属于不同的层次结构分支,建立连接是 SubInner 的工作,可以这么说。

显式委托在逻辑上和语言定义上都尊重上述所有内容,因此考虑到适当的访问,它应该是 "correct" 的方式,但由于冗余,它在实现中容易出错(如果我在 SubInner.innerDoSomething()?)

中调用 SuperInner.innerDoSomethingElse()

最终:例如,我可以使用一些 python 脚本来自动执行显式委派(我确实自动创建了具有类似冗余弱点的构建器模式),或者干脆放弃增加的访问安全性控制并使受保护成员public.