英文:
Why does a superclass reference calling an overridden method appear polymorphic, but not if it takes an overridden member variable?
问题
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass = new BClass("han", "男");
AClass aClass = bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
这个类的执行结果是:
男
null
这些结果让我感到困惑。当超类调用被覆盖的方法时,结果符合我的预期,但当它调用被覆盖的成员变量时,结果却让我困惑。所以为什么超类引用调用被覆盖的方法时会出现多态性,但调用被覆盖的成员变量时却不会呢?以下是完整的代码。
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass = new BClass("han", "男");
AClass aClass = bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
package main.java;
public class AClass {
private String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
package main.java;
public class BClass extends AClass {
private String sex;
public BClass(String name, String sex) {
this.sex = sex;
super.setName(name);
}
@Override
public String getSex() {
return sex;
}
@Override
public void setSex(String sex) {
this.sex = sex;
}
}
英文:
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass=new BClass("han","男");
AClass aClass=bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
The execution result of this class is
男
null
The results are confusing to me. When the superclass calls the overridden method, the results meet my expectations, but when it calls the overridden variable, the results confuse me.so why does a superclass reference calling an overridden method appear polymorphic, but not if it takes an overridden member variable?Here's the entire code.
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass=new BClass("han","男");
AClass aClass=bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
package main.java;
public class AClass {
private String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
package main.java;
public class BClass extends AClass{
private String sex;
public BClass(String name,String sex) {
this.sex = sex;
super.setName(name);
}
@Override
public String getSex() {
return sex;
}
@Override
public void setSex(String sex) {
this.sex = sex;
}
}
答案1
得分: 2
在子类中,虽然你可以重写一个方法,但无法重写一个字段;实际上,你只是声明了一个具有相同名称的字段。要允许该字段在子类中可见,你可以将其可见性更改为protected
或包私有(默认修饰符),如果这两个类在同一个包中的话。演示。
public class BClass extends AClass {
public BClass(String name, String sex) {
this.sex = sex;
super.setName(name);
}
@Override
public String getSex() {
return sex;
}
@Override
public void setSex(String sex) {
this.sex = sex;
}
}
public class AClass {
protected String name, sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
英文:
While you can override a method, you can't override a field in a subclass; you are actually just declaring a field with the same name. To allow the field to also be visible in the child class, you can change its visibility to protected
or package private (default modifier), if both classes are in the same package. Demo.
public class BClass extends AClass{
public BClass(String name,String sex) {
this.sex = sex;
super.setName(name);
}
@Override
public String getSex() {
return sex;
}
@Override
public void setSex(String sex) {
this.sex = sex;
}
}
public class AClass {
protected String name, sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
答案2
得分: 0
根据Java规范,在子类继承时,实例变量不会被子类从超类中覆盖。
英文:
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
答案3
得分: 0
Java不允许你真正覆盖一个字段。
你的BClass
实际上有两个名为sex
的字段,一个来自AClass
,一个来自BClass
。而Java的语法并没有真正帮助你找出在像x.sex
这样的情况下指的是哪一个字段。就好像你在AClass
中定义了一个名为sex_a
,在BClass
中定义了一个名为sex_b
的两个不同字段,只是在这种情况下,对这两个字段的引用都写成了x.sex
,没有明确的提示指出是哪一个字段。
在你的情况下:
- 你的
BClass
实例将初始化其sex_b
,而sex_a
为空(null)。 aClass.getSex()
始终调用最具体的方法,基于实例的运行时类,即BClass
。因此它选择来自BClass
的方法,返回sex_b
,因此打印性别。aClass.sex
访问两个sex
字段中的一个,取决于变量的编译时可推导类型,在你的情况下是AClass
。所以它打印sex_a
的值,即null。
经验丰富的Java开发人员通常会尽力避免这种情况,因为它可能会非常令人困惑。
如果这两个字段在概念上具有相同的含义,就像你在name
字段中所做的那样,只在父类中有一个字段,并让子类通过getter和setter访问它(或者通过声明protected
可见性来访问字段)。
如果这两个字段在概念上具有不同的含义(一个对象可以有两种不同的性别吗?),请使用不同的名称。
英文:
Java doesn't allow you to really override a field.
Your BClass
actually has two fields named sex
, one from AClass
, and one from BClass
. And Java syntax doesn't really help you finding out which one is meant when you write something like x.sex
. It's as if you had defined two different fields, sex_a
in AClass
and sex_b
in BClass
, only with the complication that references to both are written like x.sex
, without a clear hint which of the two is meant here.
In your case:
- Your BClass instance will have its
sex_b
initialized, and thesex_a
empty (null). aClass.getSex()
always calls the most specific method, based on the instance's runtime class, beingBClass
. So it chooses the method fromBClass
, returningsex_b
, and thus prints the sex.aClass.sex
accesses one of the twosex
fields, depending on the variable's compile-time-deducible type, in your case beingAClass
. So it prints thesex_a
value, being null.
Seasoned Java developers typically do their best to avoid this situation, as it can be very confusing.
If the two fields conceptually have the same meaning, do it as you did with the name
field, having only one field in the parent class, and have the subclass access it via getters and setters (or by declaring protected
visibility for the field).
If the two fields have conceptually different meanings (can an object have two different sexes?), use different names.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论