繁体   English   中英

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

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

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

它是:

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

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

一切都很好,因为外部的Outer类被允许访问嵌套的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!
        //...
    }
}

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

使它起作用的唯一方法似乎是为每种方法添加显式委派,例如:

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

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

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

怎么会? SubOuter是否应该禁止并访问innerDoSomething()保护的访问并进行访问?

无法通过变量引用从其他程序包访问受保护的方法。 如果SuperOuter和SubOuter这两个类位于同一软件包中,则它将起作用。

好的,我想我已经解决了,仔细地重新阅读了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模式的自动创建),或者只是放弃了增加访问控制的安全性并公开了受保护的成员。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM