Я работаю ниже кода Java и не могу понять, почему он возвращает 0 в качестве вывода вместо 200 или 500.
class Bike{
int speedlimit;
}
class Honda3 extends Bike{
int speedlimit;
public static void main(String args[]){
Bike obj=new Bike();
obj.speedlimit=200;
Honda3 obj2=new Honda3();
obj2.speedlimit=500;
obj=obj2;
System.out.println(obj.speedlimit);
}
}
Выход: 0
Вы видите 0, потому что вы используете два отдельных атрибута ограничения скорости, один для класса Bike, а другой для класса Honda3, вы можете просто удалить атрибут из класса Honda3, потому что он наследует его от класса Bike.
В этой строке obj.speedlimit
вы присваиваете атрибут Bike, а в другой руке obj2.speedlimit
присваиваете атрибут Honda3.
Когда вы назначаете obj = obj2
, а затем получаете доступ к атрибуту ограничения скорости из obj
, вы больше не используете атрибут класса Honda3, а атрибут класса Bike, который еще не был назначен.
Если вы удалите атрибут ограничения скорости из класса Honda3, ваша проблема исчезнет.
Когда вы определяете поле в подклассе, которое имеет то же имя, что и поле в суперклассе, вы не переопределяете поле, а только «скрываете» его для пользователей подкласса.
Таким образом, когда вы создаете Honda3, вы создаете объект с двумя полями ограничения скорости: поле класса Bike инициализируется нулем (поскольку это значение по умолчанию для целых чисел), а поле класса Honda3 устанавливается равным 200. Затем, когда вы " используйте Honda3 как «Велосипед», поле ограничения скорости для класса «Велосипед» больше не скрыто и распечатывается по стандарту.
Потому что obj2 = obj
назначает экземпляр Honda3
со скрытым полем Bike.speedlimit
, которое по умолчанию инициализируется 0
new Bike()
с speedlimit
переменной экземпляра 0
создается, а затем назначается 200
new Honda3()
создается с переменной экземпляра speedlimit = 0
и Bike.speedlimit = 0
, который наследуется от Bike
, тогда speedlimit
присваивается 500
. Honda3
скрывает Bike
speedlimit
Когда вы присваиваете obj = obj2
, вы выполняете приведение вверх и ссылаетесь на Honda
как на Bike
, а System.out.prinln(obj.speedlimit)
печатает Bike.speedlimit
, наоборот, если бы вы делали понижающее приведение System.out.println(((Honda3) obj).speedlimit)
, вы получили бы 500
Также полиморфизм времени выполнения или динамическая диспетчеризация работают только для методов, а не для элементов данных. Методы переопределяются, но поля скрыты.
После obj = obj2
Когда вы создаете объект Honda3
, созданный объект также включает в себя все поля родительского класса, то есть Bike
. Все поля инициализируются значением по умолчанию (speedlimit = 0
). Также при создании объекта мы не можем отбросить поле speedlimit
велосипеда только потому, что Honda3
имеет поле с таким же именем. Мы не говорим компилятору переопределить поле, поэтому компилятор будет включать оба поля speedlimit
внутри объекта Honda3
, как это:
Итак, если вы присваиваете объект Honda3
переменной типа Bike
, вы можете получить доступ к скрытому speedlimit
через эту переменную. Пожалуйста, обратитесь к изображению ниже, чтобы визуализировать весь процесс.