Вопрос

Я готовлюсь к экзамену и нашел примерную задачу, из-за которой я совершенно растерялся.Для следующего кода найдите, каков результат:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe()); 
        ((Curly)stooge1).print(new Larry()); 
        ((Larry)stooge2).print(new Moe()); 
        stooge2.print(new Curly()); 
        stooge3.print(new Curly()); 
        stooge3.print(new Moe()); 
        stooge3.print(new Larry()); 
        ((Curly)stooge3).print(new Larry()); 
        ((Curly)stooge3).print(new Curly()); 
        stooge4.print(new Curly()); 
        stooge4.print(new Moe()); 
        stooge4.print(new Larry()); 
        stooge5.print(new Curly()); 
        stooge5.print(new Larry()); 
        stooge5.print(new Moe()); 
    }
}

У меня были свои идеи в голове, но потом, когда я запустил java, я получил нечто совершенно другое:

Curly 1
Curly 2
Larry 1
Larry 1
Curly 1
Curly 1
Curly 1
Curly 2
Curly 3
Curly 3
Curly 1
Curly 2
Larry 2
Larry 2
Larry 1

Первые несколько слов в порядке, но потом я действительно не понимаю.У кого-нибудь есть хорошее объяснение этой проблемы?

Спасибо

Это было полезно?

Решение

Я бы начал с того, что нарисовал картинку...

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)

Тогда я бы отслеживал переменные:

  • Ларри - марионетка 1 -> Кудрявый
  • Мо - марионетка 2 -> Ларри
  • Мо - марионетка 3 -> Кудрявый
  • Кудрявый - stooge4 -> Кудрявый
  • Ларри - марионетка 5 -> Ларри

  • stooge1.print(new Moe())

    • stooge1 -> Кудрявый, поэтому вызывает Curly.print(Moe)
  • ((Curly)stooge1).print(new Larry());

    • stooge1 -> Curly так называет Curly.print(новый Larry())
  • ((Larry)stooge2).print(new Moe());

    • stooge2 -> Ларри так называет Ларри.print(новый Moe());
  • stooge2.print(new Curly());
    Хорошо, здесь все становится немного сложнее (извините, что я остановил один из них раньше здесь)

    • stooge2 объявлен Мос.Таким образом, когда компилятор ищет, что вызвать, он собирается вызвать метод print(Moe).Затем во время выполнения он знает, что stooge2 - это Larry, поэтому вызывает метод Larry.print(Moe).

и т.д...

Дайте мне знать, если, следуя этому до конца, у вас ничего не получится.

(обновлено, чтобы прояснить следующий)

Итак, общее правило таково:

  • компилятор смотрит на тип переменной, чтобы решить, какой метод вызывать.
  • среда выполнения просматривает фактический класс, на который указывает переменная, чтобы решить, откуда получить метод.

Итак, когда у вас есть:

Moe stooge2 = new Larry();
stooge2.print(new Moe());

компилятор говорит:

  • можно ли назначить Ларри в stooge2?(да, поскольку Ларри является подклассом Moe)
  • есть ли у Moe метод печати (Moe)?(да)

среда выполнения говорит:

  • Предполагается, что я должен вызвать метод print (Moe) для этого объекта here ...марионетка 2
  • stooge2 указывает на Ларри.
  • Я вызову метод print(Moe) в классе Larry.

Как только вы со всем этим разберетесь, попробуйте избавиться от некоторых методов и посмотрите, как это все меняет.

Другие советы

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

Общее правило, упомянутое TofuBeer, верно только в случае динамической привязки.При статическом привязывании решения принимаются только во время компиляции.

В вашем примере смешивается динамическая привязка (когда методы переопределены) и статическая привязка (когда методы перегружены).

Взгляните на этот вопрос для получения более подробной информации.

Подсказка заключается в том, чтобы не обращать внимания на значение слева при просмотре объектов.Вместо этого посмотрите на значение права во время объявления, это фактическое значение объекта.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top