按值传递&多态性

时间:2015-09-18 12:44:10

标签: java inheritance polymorphism pass-by-value

我对编程很新,并且不明白为什么这段代码打印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;
    }
}

3 个答案:

答案 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;
    }
}