Перегрузка, переопределение и связывание в Java - PullRequest
0 голосов
/ 07 января 2020

У меня есть вопрос относительно того, каким будет вывод следующего кода, и, что более важно, - почему он будет таким?

class Animal {
    public void makePair(Animal a) {
        System.out.println("A pair of animals");
    }
}

class Shark extends Animal{
    public void makePair(Shark s) {
        System.out.println("A pair of sharks");
    }
}

class Duck extends Animal {
    public void makePair(Duck d) {
        System.out.println("A pair of ducks");
    }
}

public class Main {
    public static void main(String[] args) {
        Shark bruce = new Shark();
        Shark anchor = new Shark();
        Animal donald = new Duck();
        Duck daffy = new Duck();
        bruce.makePair(anchor);
        donald.makePair(daffy);
        anchor.makePair(daffy);
    }
}

Ответы [ 3 ]

0 голосов
/ 08 января 2020

Выводит:

Пара акул

Пара животных

Пара животных

Вы не отменяете Animal в 2 классах, которые его расширяют, так что Duck и Shark будут иметь по 2 версии, а Java "найдет" правильный метод.

В вашем примере:

bruce.makePair(anchor);

Печать "Пара акул", потому что оба Shark

donald.makePair(daffy);

Печатает «Пара животных». Дональд - это Duck, но объявляется Animal, поэтому он имеет доступ только к Animal.makePair(), а Даффи расширяется Animal, так что это приемлемо.

anchor.makePair(daffy);

Печатает «Пара животных», потому что якорь Shark и daffy a Duck, единственная работающая подпись метода - Animal.

0 голосов
/ 08 января 2020

Компилятор решает, какой метод вызывать на основе предоставленной вами информации.

Ни один из этих методов не перекрывает друг друга, поскольку каждый из них имеет различную подпись. Подпись состоит из имени метода, количества аргументов и типов аргументов.

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

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

  • Вы объявили Shark bruce и Shark anchor, поэтому компилятор знает, что Брюс и якорь имеют тип Shark. Поэтому он выбирает наиболее конкретный метод c класса Shark: метод makePair(Shark s).
  • Вы объявили Animal donald, поэтому компилятор знает только, что donald имеет тип Animal. Не имеет значения, что вы на самом деле присвоили ему, потому что компилятор не запускал этот код. То, что знает компилятор, это то, что вы сказали ему, и это то, что donald имеет тип Animal, и этот тип имеет только один метод, поэтому вызывается метод makePair(Animal a).
  • Компилятор знает, что anchor имеет тип Акула, но Даффи имеет тип Утка. Shark объявляет свой собственный метод makePair, который принимает аргумент типа Shark, но аргумент daffy не соответствует этому, поэтому единственный метод, который может соответствовать, - это метод makePair(Animal a), который Shark наследует от Animal.
0 голосов
/ 08 января 2020

Ваш вопрос о полиморфизме, вы можете прочитать его на Полиморфизм в Java

В текущем случае выход будет

Пара Акулы

Пара животных

Пара животных

Объяснение

Эти строки

Shark bruce = new Shark();
Shark anchor = new Shark();
Animal donald = new Duck();
Duck daffy = new Duck();

утверждают, что Брюс - акула, якорь - акула, Дональд - утка, а Даффи - утка.

Во-вторых, строки, написанные ниже

class Shark extends Animal
class Duck extends Animal

, указывают, что и Акула, и Утка являются животными, плюс в каждом классе есть метод с именем makePair (). Теперь давайте перейдем к выводу, что, как это произошло

, первая строка вывода пришла от

bruce.makePair(anchor);

, поскольку мы уже знаем, что Брюс и якорь являются акулами, а метод, представленный в классе акул, является

public void makePair(Shark s) {
    System.out.println("A pair of sharks");
}

, который показывает, что он принимает Акулу (тот же объект класса) в качестве параметра, поэтому он пришел таким образом.

Теперь переходим к последней строке вывода, которая

anchor.makePair(daffy);

поскольку мы знаем, что anchor - это акула, а Daffy - утка, теперь в этом случае компилятор проверяет, что метод, определенный в классе Shark, принимает утку в качестве параметра, если нет, он проверяет свой родительский класс, который есть метод, который принимает утку в качестве параметра. В этом случае метод, определенный в родительском классе

public void makePair(Animal a) {
    System.out.println("A pair of animals");
}

, не принимает утку, но принимает животных, и мы знаем, что и акула, и утка - животные, поэтому это напечатано. Теперь давайте перейдем к самой захватывающей строке вывода в одну секунду, которая состоит из

donald.makePair(daffy);

, оба - утки, но результат - пара животных, потому что давайте вспомним определение объекта Дональда

Animal donald = new Duck();

здесь вы можете увидеть ссылку на родительский класс и объект дочернего класса. Теперь, когда возникает случай, объект определяется таким образом, и родительский и дочерний объекты имеют функцию с одинаковым именем ( Overloading ). Выполняемая функция является функцией ссылочного класса (который является родительским (Animal) классом) в этом случае, поэтому мы получили такой вывод.

...