#java #jvm #полиморфизм
Всем доброго времени суток. Только начал готовиться к собеседованию на Java Junior`а, как произошло небольшое недопонимание по поводу полиморфизма. Я изучал Java Core по книге Кэти Сьерра и Берта Бейтса("Изучаем Java. 2-е издание"). Там механизм наследования (и вообще хранения объектов в куче JVM) представлялся вот так: public class A{ //code... } public class B extends A{ //code... } public class TestApp{ public void init(){ B val = new B(); } } И в JVM это все выглядит таким образом: Допустим, у нас есть такой код: public class Animal{ public void makeSomthing(){ System.out.println("Animal"); } } public class Dog extends Animal{ //переопределенный метод @Override public void makeSomthing(){ System.out.println("Dog"); } public void fMagic(){ this.makeSomthing(); //Console: Dog super.makeSomthing(); //Console: Animal [?] } } public class TestApp{ public static void main(String[] args){ Dog dogPet = new Dog(); dogPet.fMagic(); } } Выходит, что при вызове метода fMagic() у объекта dogPet так же вызывается метод makeSomthing() у "внешнего" объекта Dog и еще этот же метод вызывается у "внутреннего" объекта Animal(у суперкласса). Как я понял, по логике этой книги, конструкция переопределения(@Override) методов заключается в том, что метод по сути один, а когда мы его переопределяем, то как-бы изменяем его во "внутреннем" объекте c помощью "внешнего". А уже при вызове dogPet.fMagic() он вызывается изнутри. Но при этом: класс Dog public void fMagic(){ this.makeSomthing(); //Console: Dog super.makeSomthing(); //Console: Animal [?] //Console: Dog@74a14482 - адрес Dog. Dog@74a14482 - адрес Animal. System.out.println("links:"+"\n" + this + " - адрес Dog. "+ super.getObjectLink() + " - адрес Animal."); } класс Animal public Object getObjectLink(){ return this; } Но самое странное на мой взгляд заключается вот в этом: При сужении типа до его родителя, вызов функции дает "Dog", а не "Animal". Т.е в данном случае, переопределение метода в классе Dog изменяет метод saySomthing(). А вот в случае вызова метода fMagic() у класса Dog, вызываются 2 разные функции И переопределение функции суперкласса, как я понимаю, ничего не дает. Animal dogPet = new Dog(); dogPet.makeSomthing(); //Console: Dog Суть вопроса: Как же именно все эти процессы и механизмы ООП происходят на самом деле? И почему же при вызове fMagic() на консоль выводится две разные надписи "Dog" и "Animal", а не одна и та же надпись "Dog", как в случае с Animal dogPet = new Dog();?
Ответы
Ответ 1
Во-первых завязывайте с такой терминологией, нет никаких внешних и внутренних объектов. У вас есть класс Dog, который расширяет класс Animal. Наследование представляет собой отношение типа является(is a). Следовательно в Вашем случае объект Dog является объектом Animal, а значит содержит в себе его поведение. Поведение родительского класса может использоваться в подклассе при помощи ключевого слова super, что Вы и продемонстрировали. Ключевое слово this используется для получения объектом ссылки на самого себя, что в данном случае делается по-умолчанию. Т.е. Вы получите такой же результат если опустите его. Чтобы лучше понять преимущества полиморфизма разберите паттерн проектирования "Стратегия". На мой взгляд один из самых ярких примеров. Также если Вы пишете Animal dog = new Dog(); Вы говорите машине: "Создай мне объект Dog и помести его в переменную типа Animal". Вы можете это сделать, поскольку Dog является Animal. Однако обращаясь к этой переменной у Вас будет вызываться метод класса Dog поскольку в ней содержится объект Dog. Animal здесь - это тип переменной, а не объекта.
Комментариев нет:
Отправить комментарий