【问题标题】: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 标签。
  • 是的,这很好。顺便说一句,接受的答案需要一些更正。

标签: java subclass packages protected access-modifiers


【解决方案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 修饰符公开它
猜你喜欢
  • 2020-08-02
  • 2016-03-08
  • 1970-01-01
  • 2012-06-23
  • 2013-07-10
  • 2021-12-31
  • 2013-11-25
  • 2020-01-10
相关资源
最近更新 更多