Переопределенные и перегруженные методы - PullRequest
1 голос
/ 11 июня 2019

Что означает «приведение влияет на выбор перегруженных методов во время компиляции, но не переопределенных методов»?

Я прочитал следующий отрывок "Переопределенные методы и динамическое связывание" (https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html), и я не смог понять последний абзац

"В предыдущем разделе мы упоминали, что перегруженные методы выбираются компилятором во время компиляции. С другой стороны, переопределенные методы выбираются динамически во время выполнения. Даже если мы создаем экземпляр подкласса, наш код никогда не ранее (возможно, новый класс, загруженный по сети), любые переопределяющие методы, которые он содержит, находятся и используются во время выполнения, заменяя те, которые существовали, когда мы в последний раз компилировали наш код.

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

Я не мог понять строку «Casting»: «Другой эффект этого заключается в том, что приведение (то есть явное указание компилятору обрабатывать объект как один из его присваиваемых типов) влияет на выбор перегруженных методов во время компиляции, но не переопределяется методы ".

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Эта строка относится к тому факту, что

  • перегруженные версии метода выбираются во время компиляции на основе типов времени компиляции передаваемых аргументов;тогда как
  • переопределенные методы выбираются во время выполнения на основе классов объектов, для которых вы вызываете каждый метод.

Чтобы понять это различие, рассмотрим ситуацию, когдау вас есть как переопределения, так и перегрузки, например:

public class Person {
}
---------------------------------------------------------
public class Postman extends Person {
}
---------------------------------------------------------
public class Dog {
    public void barkAt(Person p) {
        System.out.println("Woof woof");
    }

    public void barkAt(Postman p) {
        System.out.println("Grrrr");
    }
}
---------------------------------------------------------
public class Rottweiler extends Dog {
    @Override
    public void barkAt(Person p) {
        System.out.println("I'm going to eat you.");
    }

    @Override
    public void barkAt(Postman p) {
        System.out.println("I'm going to rip you apart.");
    }
}

В этой ситуации мы вызываем один из этих barkAt методов, например:

Dog cujo = new Rottweiler();
Person pat = new Postman();
cujo.barkAt(pat);

Теперь в данном конкретном случаеКомпилятор выбирает, будет ли cujo.barkAt(pat); вызывать метод, подобный public void barkAt(Person p) или public void barkAt(Postman p).Эти методы являются перегрузками друг друга.

Для этого компилятор проверяет тип выражения, передаваемого методу, то есть переменную pat.Переменная pat имеет тип Person, поэтому компилятор выбирает метод public void barkAt(Person p).

Что компилятор не делает, это выбирает, является ли этот метод из Rottweiler class или Dog class, который вызывается.Это происходит во время выполнения на основе класса объекта, для которого вызывается метод, а НЕ на типе переменной, для которой вызывается метод.

Итак, в данном случае важен класс объекта, который называется cujo.И в этом примере cujo - это Rottweiler, поэтому мы получаем переопределенную версию метода - определенную в классе Rottweiler.

В этом примере будет напечатано I'm going to eat you.

Подводя итог:

  • Перегрузка выбирается при время компиляции на основе параметра тип .
  • Переопределение выбирается при времени выполнения на основе объекта class .

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

cujo.barkAt((Postman) pat);

На этот раз передаваемый методу параметр является выражением типа Postman.Компилятор соответственно выбирает перегрузку, и это выдает I'm going to rip you apart..

0 голосов
/ 11 июня 2019

Приведение влияет на выбор перегруженных методов во время компиляции, но не переопределенных методов

Перегруженные методы видны во время компиляции. Но переопределенные методы становятся видимыми во время выполнения.

Правило большого пальца:

Java вызывает переопределенные методы на основе содержимого ссылочной переменной, а не типа ссылочных переменных.

Ниже приведен самоочевидный пример. Надеюсь, это поможет.

class Animal {
    public void speak() {
        System.out.print("Animal sounds/roars.");
    }
}

class Human extends Animal {
    @Override                     // Method is overridden
    public void speak() {
        System.out.print("Humans talking english.");
    }

    public void speak(String words) {         // Method is overloaded.
        System.out.print("We have brain. We are intelligent."+words);
    }
}

class Earth {
    public static void main(String a[]) {
        Animal a = new Animal();
        a.speak(); // Prints Animal sounds/roars.

        Human h = new Human();
        h.speak();    // Prints "Humans talking english."

        Animal a = h; // Cast to superclass reference variable. However, underlying object is of Human.
        a.speak();    // Prints "Humans talking english." because speak() is known by Animal at compile time. During runtime, 
                      // the object contains the human object and hence java calls human overridden method.

        a.speak("I want to be human."); // Compile time error as speak(..) is not known by Animal at compile time.

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...