YAIC (ще одна помилка спадкування)

Я впевнений, що цей тип запитань запитує щодня, але я бореться з розумінням, чому об'єкт ссавця вказується як кішка, і повідомляє про його ім'я як Морріс. Проте, на відміну від більшості кішок, він не має 9 життів. Якщо об'єкт не є кішкою, чому він повідомляє про своє ім'я, щоб бути Моррісом?

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());  
    }
}
0
Ви читаєте Cat як Mammal .
додано Автор Prince John Wesley, джерело

4 Відповіді

Тут є два пов'язані, але конкретно окремі поняття.

  1. Тип виконання об'єкта
  2. Статичний тип (і тип виконання) змінної.

Тип виконання об'єкту визначатиме, як він поводиться під час виконання. Це визначається конструктором, який ви зателефонували, коли ви використовували ключове слово new .

Статичний тип змінної вказує на те, як ваш код може взаємодіяти або посилання на цю змінну (і на об'єкт, на який вона посилається). Він визначається типом, який ви вказали, коли ви заявляєте цієї змінної (або поля, параметри тощо).

У цьому випадку статичний тип змінної - Mammal , тоді як тип виконання об'єкта, до якого він вказує, є Cat . Таким чином, в той час, коли він веде себе як Cat під час виконання, і його ім'я називається "Morris", під час компіляції компілятор знає, що це Mammal , і не може передати до змінної lives (яка визначається в Cat , а не Mammal ).

3
додано
Так звучить, як я задаю неправильне питання (спадкування). Замість цього я задаю питання, яке вирішувало.
додано Автор EdgeCase, джерело
@Перцепція: дякую за редагування.
додано Автор Mark Peters, джерело
+1, чудовий відповідь.
додано Автор Perception, джерело

Оскільки змінна має тип Mammal , який був встановлений у рядку Mammal mm = new Cat (); . Клас Mammal не містить змінної lives , тому він викидає цю помилку. Однак, якщо ви виконуєте ((Cat) mm) .lives , ви повинні отримати правильний результат, оскільки ви віддаєте змінну mm типу Cat (який був ініціалізований як).

EDIT

Також ви перевизначили метод getName() в класі Cat , який "приховує" клас Mammal . Ви створили mm як тип Mammal , але насправді це Cat , тобто виклик методу getName() на mm буде викликати дочірний метод getName() , який повертає "Morris" замість "George" .

2
додано
Перевантажені або перевизначені? Я думав, що я відвернув їх метод.
додано Автор EdgeCase, джерело
@BusterBunker Ви правильно, це було переоцінено, це була моя помилка. Я це виправити.
додано Автор Brandon Buck, джерело

об'єкт, створений в Cat, таким чином, метод getName, коли він викликається, знаходиться на об'єкті Cat, і тому його ім'я повідомляється як "morris". Однак локальна мінлива визначається як ссавця, тому життя не може бути доступним, якщо ви явно не передаєте її коту.

1
додано

Ви створили екземпляр Cat , але ви розглядаєте його як Mammal . Mammal.lives не існує, тому ви отримаєте помилку під час спроби надрукувати mm.lives .

До речі, це хороший приклад того, чому спадкування може бути небезпечно і слід використовувати з обережністю. Кішка і ссавців тісно пов'язані у спадок, так що ви повинні розуміти обидва класи і як вони взаємодіють для того, щоб зрозуміти код, який працює з кодом <> Cat .

1
додано
ІТ КПІ - Java
ІТ КПІ - Java
436 учасників