Upcasting / Downcasting в Java - PullRequest
       32

Upcasting / Downcasting в Java

0 голосов
/ 06 ноября 2019

Я пытаюсь понять, что такое upcasting и downcasting в Java, и меня смущает следующий сценарий (о моем коде, который приведен ниже):

Во-первых, почему код не компилируется, когда явключите строку myAnimal.bark();,

и Second - (при условии, что я закомментирую myAnimal.bark();), почему вызов myAnimal.move() print "moveDog" вместо "moveAnimal"? Не ограничивается ли myAnimal методами из класса Animal, потому что мы объявили его тип Animal, хотя мы устанавливаем для него тип Dog?

Любая помощьвысоко ценится! Вот код:

    public class Animal {
        public void move() {
            System.out.println("moveAnimal");
        }

       public static void main(String[] args) {
          Dog myDog = new Dog();
          Animal myAnimal = myDog;
          myAnimal.move();
          //myAnimal.bark();
       }
    }

    class Dog extends Animal {
        @Override
        public void move() {
           System.out.println("moveDog");
        }

        public void bark() {
            System.out.println("bark");
        }
    }


Ответы [ 3 ]

2 голосов
/ 06 ноября 2019

С неявным повышением в этой строке:

Animal myAnimal = myDog;

Вы ничего не делаете для изменения базового экземпляра myDog. То, что вы делаете, это присваиваете переменную типа на один уровень выше в дереве наследования. По сути, это ограничивает то, какие методы могут вызываться только теми, которые определены в Animal, но не меняет способ разрешения этих методов.

Поскольку вы ограничили доступные методы только теми, которые определены в родительском классе Animal компилятор не может разрешить Dog#bark(), поскольку это метод Dog, а переменная myAnimal определена как тип Animal, у которого нет метода #bark.

#move() - это метод как Animal, так и Dog, поэтому он разрешается, но разрешается в метод, определенный в Dog, поскольку myAnimal по-прежнему ссылается на экземпляр Dog, несмотря на то, что он преграждается.

2 голосов
/ 06 ноября 2019

Здесь есть две важные концепции, которые конкурируют друг с другом.

Первая концепция - статическая типизация , что означает, что компилятор Java проверяет типы ваших выражений, переменных и методов. во время компиляции , до того, как у кода появится возможность запуска. В этом случае переменная myAnimal имеет тип Animal, а тип Animal не имеет метода bark(), поэтому myAnimal.bark() является ошибкой типа.

Вторая концепция динамическое связывание , что означает, что реализация метода выбирается на основе типа объекта во время выполнения . Поскольку myAnimal содержит ссылку на объект класса Dog, вызов метода move() вызывает реализацию этого метода, предоставленного в классе Dog.

0 голосов
/ 06 ноября 2019

Здесь вы объявили myAnimal как Animal, и каждое животное не может лаять! то есть myAnimal здесь ссылается на Animal.

Animal myAnimal = myDog;

Но наверняка Dog - это животное, которое может лаять, поэтому вам нужно явно привести в действие myAnimal, сообщив JVM, что онвведите Dog, а не Just Animal.

Так что если вы измените //myAnimal.bark ();ниже это будет работать!

((Dog) myAnimal) .bark ();

Здесь мы отлили myAnimal из Animal в Dog. следовательно, метод bark () разрешен и не вызывает проблем с компиляцией.

Надеюсь, это поможет!

...