我对编程很新,并且不明白为什么这段代码打印200而不是206.类Cat中的move方法会覆盖Animal类中的move方法。为什么'位置'在第2行的方法调用后,动物中的实例变量不会更改为206?但是,当我在类Cat中删除该方法时,实例变量DOES将更改为206.它背后的逻辑是什么?
public class Animals {
int location = 200; //line 1
public void move(int by) {
location = location+by;
}
public final static void main (String...args) {
Animals a = new Cat();
a.move(6); //line 2
System.out.println(a.location); //200, but should print 206 in my opinion
}
}
class Cat extends Animals {
int location = 400;
@Override
public void move(int by) { //if this method is removed, a.location prints 206
location = location+by;
}
}
答案 0 :(得分:8)
a.move(6); // line 2
System.out.println(a.location);
在第一行中,您正在执行Cat中的方法,这意味着您正在修改Cat
类的变量。
在第二行,您将从Animal
打印变量。
您无法在Java中覆盖变量。只有方法。
你所做的是你在location
上隐藏了实例变量Cat
,当你在Cat类中修改它时,你不再指向Animal
了。当您在Cat类中删除该变量时,您指的是Animal
Class。
答案 1 :(得分:3)
问题是您在超类和子类中定义位置。因此,有两个不同的变量。 Cat.move修改了Cat.location。但是,如果您使用基类引用来获取位置,则会获得动物的实例位置而不是猫的位置。
解决这个问题的一种方法是在Animal中标记受保护的位置,并在每个类的默认构造函数中初始化其值(200或400)。
答案 2 :(得分:2)
强制执行打印,说明您的对象实际上是Cat
:
System.out.println(((Cat)a).location); //it prints 406
解决这个问题的最好方法是正确使用Java,你不应该直接调用变量,而应该调用该方法。
这是获得你想要的更好的方法:
public class Animals {
int location = 200; //line 1
public void move(int by) {
location = location+by;
}
public int getLocation(){
return location;
}
public final static void main (String...args) {
Animals a = new Cat();
a.move(6); //line 2
System.out.println((a).getLocation()); //note we are now calling a getter method not the variable itself
}
}
class Cat extends Animals {
int location = 400;
public int getLocation(){
return location;
}
public void move(int by){
location = location+by;
}
}