gpt4 book ai didi

Java使用父类型的对象引用访问不同包中子类中的 protected 成员

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:10:10 26 4
gpt4 key购买 nike

我在两个单独的文件中有以下代码。

package animal;

public class Frog
{
protected void ribbit()
{
System.out.println("In Frog class!");
}
}





package other;

import animal.*;

public class Tadpole extends Frog

{
protected void ribbit()
{
System.out.println("In Tadpole class!");
}

public static void main(String[] args)
{
Tadpole t = new Tadpole();
t.ribbit();

Frog f = new Tadpole();
f.ribbit(); // Does not compile
}
}

分配给 Tadpole 类型的第一个 Tadpole 对象显然可以正常编译,并且对 ribbit() 的调用将针对 Tadpole ribbit() 实现。创建并分配给 Frog 引用的第二个 Tadpole 对象。但是,调用 ribbit() 会导致编译器错误。

我知道如果你在子类中创建一个子类对象并赋值给一个在子类包之外的父类(super class)引用并试图调用父类(super class)方法,这是不允许的。但在这种情况下,自从 Tadpole 对象以来,多态性不应该使对象引用“f”调用 Tadpoleribbit() 方法被分配给它?为什么这会导致编译器错误,为什么这是不允许的?

最佳答案

这与访问protected 类成员的规则有关。参见 this section来自 Java Language Specification 的详细信息,具体来说:

Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

In addition, if Id denotes an instance field or instance method, then:

  • If the access is by a qualified name Q.Id or a method reference expression Q :: Id (§15.13), where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.

  • If the access is by a field access expression E.Id, or a method invocation expression E.Id(...), or a method reference expression E :: Id, where E is a Primary expression (§15.8), then the access is permitted if and only if the type of E is S or a subclass of S.

因此在 Frog 的子类中,如果 x 是一个 ,您只能访问 x.ribbit() Frog 的子类(x 不能声明为 Frog)。

此限制存在于 protected 成员上,否则,假设 Frog 有一个 protected int 字段:

public class Frog {
protected int a = 1;

...
}

然后可以在 Frog 的子类中定义一个 public 方法:

public class TadPole extends Frog {

public int revealFieldValueOfParent(Frog frog) {
return frog.a; // imagine this was OK
}
}

然后任何其他(不相关的)类都可以通过将 Frog 传递给子类的方法来访问该字段:

public class SomeOtherClass {

public static void main(String[] args) {
TadPole tadpole = new TadPole();
Frog frog = new Frog();
int revealedValue = tadpole.revealFieldValueOfParent(frog);
// print revealedValue
}
}

编辑:

此编译器错误与多态性无关。与对象的实际类型相关的多态性是一个运行时方面,编译器不会尝试在运行时考虑变量 f 是否实际引用 Frog蝌蚪。编译器在这里所​​做的只是强制执行 protected 修饰符的规则,仅此而已。

编辑 2:

根据下面的评论,revealFieldValueOfParent(Frog frog) 方法实际上会显示 protected 的值,如果我们将其更改为revealFieldValue(TadPole frog),但您也可以使用私有(private)成员进行显示技巧(即类似于 getter 方法)。子类真正有责任知道自己在做什么。

关于Java使用父类型的对象引用访问不同包中子类中的 protected 成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31995632/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com