从不同包的另一个实例的子类调用受保护的方法

Posted

技术标签:

【中文标题】从不同包的另一个实例的子类调用受保护的方法【英文标题】:Call protected method from a subclass of another instance of different packages 【发布时间】:2013-01-02 11:28:54 【问题描述】:

我想从提供此受保护方法的类的子类中调用另一个实例的受保护方法。请参见以下示例:

public class Nano 

    protected void computeSize() 
    



public class NanoContainer extends Nano 

    protected ArrayList<Nano> children;



public class SomeOtherNode extends NanoContainer 

    // Nano Overrides

    protected void computeSize() 
        for (Nano child: children) 
            child.computeSize();            // << computeSize() has protected access in nanolay.Nano
        
    


javac 告诉我computeSize() has protected access in Nano。我看不出这是什么原因(我以为我已经在其他代码中这样做了)。我想保持这种方法受到保护,我该怎么办?

javac version "1.7.0_09"

编辑

我想提供一个精简的版本,但我没有想到这些类位于不同的包中。

nanolay.Node
nanolay.NanoContainer
nanogui.SomeOtherNode

【问题讨论】:

你能不能也显示这些类所在的包? 啊,包裹.. 没想到。我想提供一个精简版的代码。我已经编辑了问题。 您能否在问题标题中添加软件包限定条件,因为这似乎是相关的? @MiserableVariable:这可以吗?我还将instance-methods 替换为packages 标签。 是的,这很好。顺便说一句,接受的答案需要一些更正。 【参考方案1】:

不知道原因,但 JLS 在 6.6.2. Details on protected Access 中证实了这一点(强调我的):

对象的受保护成员或构造函数只能由负责实现该对象的代码从声明它的包之外访问

所以:

package P2;
public class P2 
    protected void foo() 


.........

package P2A;    
class P2A extends P2.P2 
    void bar(P2.P2 other) 
        this.foo(); // OK
        other.foo();  // ERROR
    

    void bar2(P2A other)  
        other.foo(); //OK
    
   

P2A.bar 中,可以访问对this.foo() 的调用,因为this 负责实现P2,但other.foo() 不可访问,因为other 可能不是P2A。另一方面,bar2 有一个 P2A,所以一切都很好。

现在,为什么如果它们都是相同的包,但如果它们是不同的包,则一切正常?理由是什么?我不知道也很想知道。

元评论我已经回滚了另一个用户最近的更新,因为它大大改变了答案,并且可能更适合作为***答案本身。

【讨论】:

感谢您的总结,我绝对同意您的看法。这种行为对我来说似乎不合法。 也许你可以再问一个关于原理的问题> 可能不适合这个论坛,但programmers 喜欢这类问题 为什么 other 必须是 P2A 还不足以让它成为 P2.P2 来访问 foo();,因为 foo 是在 P2.P2 中声明的。请澄清 "从同一个包外访问受保护成员或受保护方法不能使用父类对象,只有实现类对象才能访问同一个包外父类的受保护成员" 如果我写成 P2 p = new P2A(); p.foo();即使这样也是不允许的,我想知道为什么?【参考方案2】:

您可以通过子类化和覆盖来访问受保护的方法;当它们在同一个包中可用时。我会补充一些细节。 你可以在这里阅读details。

您的示例位于 java 中 Object 类中可用的 protected clone() 方法的行上;您不能直接在任何对象上调用它(尽管所有对象都隐式地从 Object 类扩展)。

【讨论】:

但是我不能像上面那样子类化并在超类的另一个实例上调用该方法? (假设它们在不同的包中,因为它们在同一个包中时有效) someothernode 对象的实例可以访问受保护的 computeSize 方法,但不能访问 someothernode 的其他实例 - 所以不在 for 循环中。 @Scorpion 似乎不正确。如果它们都在同一个包中,则编译不会出错。 clone 无法调用,因为它是protected in Object,在包java.lang 中,而这个类不在那个包中。 是的,如果所有类都在同一个包中,它将正确编译。克隆示例说明 - 不能调用不同包中的受保护方法;所以你在 java.lang 之外创建了一个雇员类,所以不能调用这个雇员类对象上的 clone 方法,除非它通过 public 修饰符公开它

以上是关于从不同包的另一个实例的子类调用受保护的方法的主要内容,如果未能解决你的问题,请参考以下文章

无法访问子类中的受保护方法[重复]

从Ruby中的实例方法调用受保护的类方法

为啥受保护的修饰符在 Java 子类中的行为不同?

受保护的静态方法访问

将受保护的 Objective-C 实例变量公开给子类

Scala:如何使子类(在其他实例上)可以访问受保护的方法?