#java
#java
Вопрос:
Я уверен, что такого рода вопросы задают каждый день, но я изо всех сил пытаюсь понять, почему объект mammal создается как cat и сообщает, что его имя — Моррис. Однако, в отличие от большинства кошек, у него нет 9 жизней. Если объект не является cat, почему он сообщает, что его имя — Morris?
class Mammal {
int temp;
String name = "George";
public Mammal() {
temp = 98;
}
public String getName() {
return name;
}
}
class Cat extends Mammal {
int lives;
String name = "Morris";
public Cat() {
lives = 9;
}
public String getName() {
return name;
}
}
public class Inheritance {
public static void main(String[] args) {
Mammal mm = new Cat();
System.out.println("Mam Temp:" mm.temp);
//System.out.println("Cat Lives:" mm.lives); <-- error
System.out.println("Mam Name:" mm.getName());
}
}
Комментарии:
1. Вы просматриваете
Cat
какMammal
.
Ответ №1:
Здесь есть два связанных, но конкретно отдельных понятия.
- Тип объекта во время выполнения.
- Статический (и во время выполнения) тип переменной.
Тип объекта во время выполнения будет определять, как он ведет себя во время выполнения. Это определяется конструктором, который вы вызывали при использовании new
ключевого слова.
Статический тип переменной определяет, как ваш код может взаимодействовать с этой переменной или ссылаться на нее (и объект, на который она ссылается). Это определяется типом, который вы указываете при объявлении этой переменной (или поля, параметра и т. Д.).
В этом случае статический тип переменной Mammal
равен, а тип среды выполнения объекта, на который она указывает, равен Cat
. Таким образом, хотя Cat
во время выполнения он ведет себя как a и показывает свое имя как ‘Morris’, во время компиляции компилятор знает только, что это a Mammal
, и не может ссылаться на lives
переменную (которая определена в Cat
, not Mammal
).
Комментарии:
1. Похоже, я задаю неправильный вопрос (наследование). Вместо этого я задаю вопрос о кастинге.
Ответ №2:
Потому что переменная имеет тип Mammal
, который был установлен в строке Mammal mm = new Cat();
. Mammal
Класс не содержит переменной lives
и поэтому выдает ошибку. ((Cat)mm).lives
Однако, если вы это сделаете, вы должны получить правильный результат, потому что вы приводите mm
переменную к типу Cat
(с которым она была инициализирована).
Редактировать
Кроме того, вы переопределили getName()
метод в Cat
классе, который «скрывает» метод в Mammal
классе. Вы создали mm
как тип Mammal
, но на самом деле это Cat
так, что вызов getName()
метода on mm
вызовет дочерний метод getName()
, который возвращает "Morris"
вместо "George"
.
Комментарии:
1. Перегружен или переопределен? Я думал, что переопределил их метод.
2. @BusterBunker Вы правы, это было переопределено, что было моей ошибкой. Я это исправлю.
Ответ №3:
Вы создали экземпляр Cat
, но рассматриваете его как Mammal
. Mammal.lives
не существует, поэтому при попытке печати вы получаете сообщение об ошибке mm.lives
.
Кстати, это хороший пример того, почему наследование может быть опасным и должно использоваться экономно. Cat и Mammal тесно связаны по наследованию, поэтому вы должны понимать оба класса и то, как они взаимодействуют, чтобы понять код, который Cat
имеет дело с.
Ответ №4:
созданный объект принадлежит Cat, поэтому метод getName при вызове находится в объекте Cat, и, следовательно, его имя сообщается как «моррис». Однако локальная переменная определяется как млекопитающее, поэтому доступ к lives невозможен, если вы явно не передадите ее cat .