Вопрос-ответ

Does polymorphism apply on class attributes in Java?

Применяется ли полиморфизм к атрибутам класса в Java?

Я знаю, что обычное использование полиморфизма в ООП происходит, когда ссылка на родительский класс используется для ссылки на объект дочернего класса, подобный этому:

Animal animal = new Animal();
Animal dog = new Dog();

И я знаю, что полиморфизм применим к методам класса, но применим ли он также к атрибуту класса? Я попытался проверить это на этом небольшом примере:

public class Main{

public static void main(String args[]){
Animal animal = new Animal();
Animal dog1 = new Dog();
Dog dog2 = new Dog();

System.out.println("Animal object name: " + animal.name);
System.out.println("Dog1 object name: "+dog1.name);
System.out.println("Dog2 object name: " + dog2.name);

animal.print();
dog1.print();
dog2.print();
}

}
class Animal{
String name = "Animal";
public void print(){
System.out.println("I am an: "+name);
}
}
class Dog extends Animal{
String name = "Dog";
public void print(){
System.out.println("I am a: "+name);
}
}

И это результат:

Animal object name: Animal
Dog1 object name: Animal
Dog2 object name: Dog
I am an: Animal
I am a: Dog
I am a: Dog

Как вы можете видеть (надеюсь, это понятно), полиморфизм отлично работает с методом print(), но с атрибутом класса "name" это зависит от ссылочной переменной.

Итак, я прав? полиморфизм не применяется к атрибутам класса?

Переведено автоматически
Ответ 1

Когда вы расширяете класс, методы переопределяются, но поля скрываются. Динамическая отправка работает для методов, но не для полей. Почему язык разработан так, бог знает почему.

Ответ 2

Нет, это не так. Переменные экземпляра являются свойствами определенного класса и не зависят напрямую от супер- или подклассов и полиморфизма.

Вы все еще можете получить доступ к обоим полям, используя "super.name" и "this.name" в Dog, но если вы используете просто "name", значение в Dog заменится. Если вам нужен другой, вам явно нужно вызвать super . Обратите внимание, что я говорю о доступе к переменным в классе Dog.

Ответ 3

Dog.name скрывается Animal.name, и это очень плохой шаблон для этого. Любая хорошая IDE предупредит вас, что вы это делаете.

Оба поля экземпляра действительно существуют, и вы можете получить доступ к обоим из Dog as this.name и super.name.

Ответ 4

Поле Animal скрыто полем Dog, вы все равно можете получить доступ к полю Animal, сославшись на него, как вы это делали.

Ожидаемого вами поведения можно добиться таким образом:

public class Main{

public static void main(String args[]){
Animal animal = new Animal();
Animal dog1 = new Dog();
Dog dog2 = new Dog();

System.out.println("Animal object name: " + animal.name);
System.out.println("Dog1 object name: "+dog1.name);
System.out.println("Dog2 object name: " + dog2.name);

animal.print();
dog1.print();
dog2.print();
}

}
class Animal {
String name = "Animal";

public void print(){
System.out.println("I am an: "+name);
}
}
class Dog extends Animal{
public Dog() {
this.name = "Dog"
}
}
java