2015-09-18 7 views
3

Я довольно новичок в программировании и не понимаю, почему этот код печатает 200 вместо 206. Метод move в классе Cat переопределяет метод перемещения в классе Animals. Почему переменная экземпляра «location» в Животные не изменяется до 206 после вызова метода в строке 2? Однако, когда я удаляю метод в классе Cat, тогда переменная экземпляра DOES изменяется на 206. Какова логика этого?Pass-by-value & polymorphism

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; 
    } 
} 
+2

ли вы использовать функцию отладки? Попробуйте ... тогда вы увидите, какой путь будет выполняться точно. – cslotty

+0

Удалите 'int location = 400' из класса' Cat'. –

ответ

8
a.move(6); // line 2 
System.out.println(a.location); 

В первой строке вы выполняете метод в Коте, который означает, что вы изменяете переменную Cat класса.

Во второй строке вы печатаете переменную от Animal.

Вы не можете переопределять переменные в Java. Только методы.

А что вы сделали, вы слежка экземпляр переменной location на Cat и при изменении, что в вашем классе кошки, вы не указывают на Animal больше нет. Когда вы удаляете эту переменную в классе Cat, вы ссылаетесь на класс Animal.

3

Проблема в том, что вы определяете местоположение как в суперклассе, так и в подклассе. Следовательно, существуют две разные переменные. Cat.move изменяет Cat.location. Однако, если вы используете ссылку базового класса для получения местоположения, вы получаете местоположение экземпляра животного вместо местоположения кошки.

Один из способов исправить это, чтобы пометить местоположение, защищенное в Animal, и инициализировать его значение (200 или 400) в конструкторе по умолчанию для каждого класса.

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; 
    } 
} 
+0

Или просто прекратите затенение в классе Cat :) –

+0

@ sᴜʀᴇsʜᴀᴛᴛᴀ еще лучше использовать метод геттера вместо: D – nafas