【问题标题】:Overridden and Overloaded Methods重写和重载的方法
【发布时间】:2019-06-11 14:37:32
【问题描述】:

“强制转换在编译时影响重载方法的选择,但不影响覆盖方法”是什么意思?

我阅读了以下关于“重写方法和动态绑定”(https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html)的段落,但我无法理解最后一段

“在上一节中,我们提到重载方法是由编译器在编译时选择的。另一方面,重写的方法是在运行时动态选择的。即使我们创建子类的实例,我们的代码也从来没有以前见过(可能是通过网络加载的新类),它包含的任何覆盖方法都在运行时定位和使用,替换我们上次编译代码时存在的方法。

相反,如果我们创建一个新类来实现一个额外的、更具体的重载方法,并用它替换类路径中的编译类,我们的代码将继续使用它最初发现的实现。这种情况会一直存在,直到我们将代码与新类一起重新编译。这样做的另一个影响是强制转换(即明确告诉编译器将对象视为其可分配类型之一)会影响编译时重载方法的选择,但不会影响重载方法。”

我无法理解“强制转换”行:“这样做的另一个影响是强制转换(即明确告诉编译器将对象视为其可分配类型之一)会影响编译时重载方法的选择,但不会被覆盖方法。”

【问题讨论】:

    标签: java methods software-design


    【解决方案1】:

    那一行是指

    • 方法的重载版本是在编译时根据您传递的参数的编译时类型选择的;而
    • 在运行时根据您调用每个方法的对象的类来选择覆盖的方法。

    要理解这种区别,请考虑同时具有覆盖和重载的情况,如下所示。

    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 类还是Dog 类中的方法。这发生在运行时,基于调用方法的对象的 class,而不是调用方法的变量的 type。 p>

    所以在这种情况下,重要的是名为cujo 的对象的类。在这个例子中,cujo 是一个Rottweiler,所以我们得到了该方法的重写版本——在Rottweiler 类中定义的那个。

    这个例子将打印出I'm going to eat you

    总结一下:

    • 重载是在编译时根据参数type选择的。
    • 覆盖是在运行时根据对象选择的。

    现在,可以使用强制转换来更改编译器对重载的选择。 不可能使用强制转换来更改覆盖的运行时选择。所以,我们可以写

    cujo.barkAt((Postman) pat);
    

    这一次,传递给方法的参数是Postman 类型的表达式。编译器相应地选择一个重载,这将打印I'm going to rip you apart.

    【讨论】:

    • 伴侣,这是我读过的最好的解释之一。您的回答是您掌握编程概念的真实证明。谢谢你的帮助!欣赏它=)
    【解决方案2】:

    强制转换影响编译时重载方法的选择,但不影响覆盖方法

    重载的方法在编译时可见。但是被覆盖的方法在运行时变得可见。

    拇指规则:

    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.
    
        }
    }
    

    【讨论】:

    • 我认为这不是重点。问题是关于转换参数的效果。你根本没有解决这个问题。
    • 更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 2023-02-05
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多