2015-10-23 5 views
0

Я хочу получить четкое представление о динамическом полиморфизме. Когда методы в дочернем классе перегружены и перегружены, я не могу определить вызовы методов.Динамический полиморфизм с параметризованными методами

Вот класс Родитель:

Родитель Класс:

public class Parent { 

    void print(Parent parent){ 
     System.out.println("I am parent classes only print method."); 
    } 
} 

Детский Класс:

public class Child extends Parent { 

    void print(Child child) { 
     System.out.println("I am child class' child print method."); 
    } 


    void print(Parent parent) { 
     System.out.println("I am Child class' parent print method "); 
    } 


} 

И это класс вызывающего абонента.

public class Caller { 

    public static void main(String[] args) { 

     Parent p = new Parent(); 
     Child c = new Child(); 
     Parent pc = new Child(); 

     p.print(p); 
     p.print(c); 
     p.print(pc); 

     c.print(p); 
     c.print(c); 
     c.print(pc); 

     pc.print(p); 
     pc.print(c); 
     pc.print(pc); 

    } 

} 

Я могу видеть вывод в консоли, но не могу понять причину вызовов метода.

+0

Похож нечетным [Посетитель] (https://en.wikipedia.org/wiki/Visitor_pattern) мне. –

+0

* «Когда методы в дочернем классе перегружены и перегружены, я не могу определить вызовы методов». * ... это никогда не должно быть так. Разрешение перегрузки в Java происходит во время компиляции, а не во время выполнения. Если компилятор может указать из вашего кода, какой метод вызывать, то вы тоже можете. – scottb

ответ

1

Рабочим просты - перегрузка разрешено во время компиляции, и перекрывая разрешено во время выполнения (полиморфизм).

Итак, давайте посмотрим, что происходит в каждом из вашего метода вызывает ...

Мы будем игнорировать вызовы с помощью Parent p = new Parent();, поскольку он не имеет перегрузок или наиважнейшие и все вызовы метода будут напрямую использовать один метод родителя "I am parent classes only print method.".

Также обратите внимание, что компилятор заботится только о ссылочном типе переменной . И время вождения заботится только о Фактический тип объекта.

Так, в заявлении Parent pc = new Child(), любой время компиляция решения о pc будет относиться к Parent и любому выполнения решения о pc будет относиться к Child.

Вот логика для других вызовов методы,

c.print(p); 
//Compiler resolves that `print(Parent)` method should be called. 
//Runtime resolves that child objects method should be called. 
//Prints "I am Child class' parent print method " 

c.print(c); 
//Compiler resolves that `print(Child)` method should be called. 
//Runtime resolves that child objects method should be called. 
//Prints "I am Child class' child print method " 

c.print(pc); 
//Compiler resolves that `print(Parent)` method should be called. 
//Runtime resolves that child objects method should be called. 
//Prints "I am Child class' parent print method " 

pc.print(p); 
//Compiler resolves that `print(Parent)` method should be called. 
//Runtime resolves that child objects method should be called. 
//Prints "I am Child class' parent print method " 

pc.print(c); //PAY ATTENTION TO THIS... 
//Compiler resolves that `print(Parent)` method should be called. 
// This is because PC is Parent type reference and compiler doesn't find `print(Child)` in Parent class, so it uses `print(Parent)`. 
//Runtime resolves that child objects method should be called. 
//Prints "I am Child class' parent print method " 

pc.print(pc); 
//Compiler resolves that `print(Parent)` method should be called. 
// This is because Compiler knows only about the variable's reference type (And PC is of type Parent). Hence `print(Parent)` would be chosen. 
//Runtime resolves that child objects method should be called. 
//During runtime, the type of the actual object is used. And PC is referring to an Child object... So `pc.print(...)` will call the child's method. 
//Prints "I am Child class' parent print method " 
+0

Не могли бы вы объяснить pc.print (pc) в некоторых подробностях. Потому что это то, что вызывает путаницу. –

+0

@BhargavJhaveri, я добавил немного больше информации ... Посмотрите, поможет ли это ... – Codebender

+0

Спасибо. Это было полезно. –

0

Этот вопрос выглядит как дубликат difference-between-method-overloading-and-overriding

Существует разница между ядром переопределение (полиморфизм) и перегрузки.

Переопределение (полиморфизм) определяется по адресу Время выполнения. Перегрузка метода определяется по адресу Время компиляции.

Компилятор идентифицирует метод для вызова на основе доступных типов бетона.

Так c.print(c); единственный вызов, который соответствует подписи: Child.print(final Child child)

+0

Основная разница между переопределением и перегрузкой метода ясна для меня. Но мне нужен сценарий выбора сценария с четким сценарием. –

0

Рассмотрим только два объекта, один P(Parent) и второй является C(Child). Теперь P может видеть только те методы и переменные, которые доступны для него. В нашем случае он имеет доступ только к методу печати только для родительского класса. Поэтому всякий раз, когда вы вызываете метод печати с использованием родительского объекта, он вызывается только методом печати родительского класса.

p.print(p); 
p.print(c); 
p.print(pc); 

Означает, что все вышеуказанные строки вызовут метод печати родительского класса, поскольку метод child недоступен для родителя.

Для объекта child, которому присвоена родительская переменная pc, он будет вызывать метод переопределения дочернего класса, который является родительским методом дочернего класса.

pc.print(p); 
pc.print(c); 
pc.print(pc); 

Теперь для метода с использованием класса C ребенок, есть две возможности вызова метода, один метод печати, который принимает parent as an argument и второй принимает child as an argument. Поэтому все зависит от того, какой аргумент вы передаете в вызове метода.

c.print(p); 
c.print(c); 
c.print(pc); 

В первом и третьем вызове, вы передаете родительский объект в качестве аргумента метода, так динамически компилятор определить, какой метод должен быть вызван согласно пройденному аргумента, поэтому дочерний класс родительский метод будет вызываться, когда родитель объект передается в качестве аргумента, иначе будет вызван дочерний метод child.

+1

Ваше неверное описание. Вызов 3 'pc.' вызовет метод дочерней печати из-за переопределения – Tim

+0

Да, мой плохой. Спасибо за исправление :) –