有人可以解释一下这里发生了什么以及为什么?
class Base{
private float f = 1.0f;
void setF(float f1){ this.f = f1; }
float getF() {return f;}
public void xx(){}
}
class Base2 extends Base{
private float f = 2.0f;
public void xx(){
System.out.println(super.getF()+" "+this.getF());
}
//float getF() {return f;} //1
//void setF(float f1){ this.f = f1; } //2
public static void main(String[]args){
Base b=new Base2();
b.setF(3);
b.xx();
System.out.println(b.getF());
System.out.println(((Base)b).getF());
}
}
此代码的输出将 3 3,3,3 。
如果我仅使用getter取消注释第1行,则输出 3 2,2,2 。
如果我只使用setter取消注释第2行,则输出 1 1,1,1 。
如果我取消注释第1行和第2行(使用setter和getter),输出将 1 3,3,3 。
//default output: 3 3, 3, 3
//with getter: 3 2, 2, 2
//with setter: 1 1, 1, 1
//with getter and setter: 1 3, 3, 3
如果使用子类中的代码覆盖父类中的方法,则该覆盖方法无法访问私有成员变量,即使父类中的重写方法也是如此。子类中的重写方法可以调用父类中的重写方法。
因此,它解释了具有getter和setter的情况#4,只能访问Base2成员变量
答案 0 :(得分:1)
您获得3 3 3 3
因为set / get方法修改了Base.f
变量:
您获得3 2 2 2
因为设置了Base.f
变量的更改值,但get方法获得了Base2.f
变量的值。
得到1 1 1 1
因为设置Base2.f
变量的方法更改值,但get方法获取Base.f
变量的值。
您获得1 3 3 3
因为super.getF()
返回Base.f
变量的值,但其他get方法返回Base2.f
变量的值。此外,set方法更改了Base2.f
变量的值。
答案 1 :(得分:1)
让我们从一些背景开始。
在Inheritance Java教程中说明:
超类中的私人会员
子类不继承其父类的私有成员。 但是,如果超类具有公共或受保护的方法 访问其私有字段,子类也可以使用它们。
在Polymorphism章节中陈述:
Java虚拟机(JVM)为其调用适当的方法 每个变量中引用的对象。它没有打电话给 由变量类型定义的方法。这种行为是 称为虚方法调用并演示了一个方面 Java语言中重要的多态性特征。
最后,在同一教程的Hiding fields章节中说明:
在一个类中,一个与该字段中的字段同名的字段 超类隐藏超类的字段,即使它们的类型是 不同。在子类中,超类中的字段不能 由简单名称引用。相反,必须访问该字段 通过超级,这将在下一节中介绍。通常 说来,我们不建议隐藏字段,因为它会使代码变得困难 阅读。
因此,子类无法直接访问超类的私有成员。但是,它们仍然存在,可以使用非私有访问器/ mutator进行访问或修改。
现在回到问题本身。
在你的第一个例子中,你既不覆盖访问者也不覆盖mutator - 你只是一直调用继承的。它们返回并修改 f of Base 的值。 为什么继承的accessor / mutator不返回/修改Base2的 f的值?因为即使 f of Base 不是私有的,也不会被覆盖,只是隐藏。
在第二个示例中,您将覆盖访问者。这是您开始涉及多态性的地方。 This short answer可能有助于理解它。当您致电b.setF(3)
时,您需要设置 f of Base 的值。但是,当您致电getF()
时,您会获得 f of Base2 的值,除非您使用关键字超级来调用它。
请注意,在您上次通话System.out.println(((Base)b).getF())
投射到 基地 时,该功能无效,因为 b 已经声明为 Base 。如果不使用 super ,就不能调用重写的超类方法(正如您所知,只能覆盖实例方法)。
在第三个示例中,您将覆盖mutator。情况与你的第二个例子相反。当您致电b.setF(3)
时,您需要设置Base2的 f的值。但是你总是从getter获得 f of Base ,因为getter不会被覆盖。因此,对getF()
的所有4次调用都会返回 f of Base 的初始值。
在上一个示例中,您重写了accessor和mutator。因此,它们在Base2的 f 上运行。唯一一个返回 f of Base 的初始值的调用显然是super.getF()
。
这绝对不是一个完美的解释,但我希望它有所帮助。