【问题标题】:Overloadin, Overriding, and Binding in JavaJava 中的重载、覆盖和绑定
【发布时间】:2020-01-07 20:43:24
【问题描述】:

我对以下代码的输出有什么疑问,更重要的是 - 为什么会这样?

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);
    }
}

【问题讨论】:

  • 你试过运行你的代码吗?如果是这样,它输出了什么?如果没有,为什么不呢?

标签: java inheritance methods binding overloading


【解决方案1】:

它输出:

一对鲨鱼

一对动物

一对动物

您没有覆盖扩展它的 2 个类中的 Animal,因此 DuckShark 将各有 2 个版本,Java 将“找到”正确的方法。

在你的例子中:

bruce.makePair(anchor);

打印“一对鲨鱼”,因为两者都是Shark

donald.makePair(daffy);

打印“A pair of animals” donald 是 Duck,但被声明为 Animal,因此它只能访问 Animal.makePair(),而 daffy 扩展 Animal,因此是可以接受的。

anchor.makePair(daffy);

打印“A pair of animals”,因为anchor 是Shark 而daffy 是Duck,唯一有效的方法签名是Animal

【讨论】:

    【解决方案2】:

    您的问题是关于多态性的,您可以在以下位置阅读 Polymorphism in 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
    

    声明 Shark 和 Duck 都是动物,而且每个类中都有一个名为 makePair() 的方法。现在让我们看看它是怎么来的输出

    第一行输出来自

    bruce.makePair(anchor);
    

    我们已经知道 bruce 和 anchor 是鲨鱼,而鲨鱼类中的方法是

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

    这表明它需要一个 Shark(相同的类对象)作为参数,所以它是这样来的。

    现在转到来自

    的最后一行输出
    anchor.makePair(daffy);
    

    我们知道anchor是鲨鱼,Daffy是鸭子,现在在这种情况下,编译器检查Shark类中定义的方法是否接受鸭子作为参数,如果没有,它将检查其父类是否有接受的方法鸭子作为参数。在这种情况下,父类中定义的方法

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

    不接受鸭子,但接受动物,我们知道鲨鱼和鸭子都是动物,所以打印出来。 现在让我们来看看最令人兴奋的一秒输出,它来自

    donald.makePair(daffy);
    

    两者都是鸭子,但输出是一对动物,因为让我们回忆一下 donald 对象的定义

    Animal donald = new Duck();
    

    在这里你可以看到父类的引用和子类的对象。现在,只要有这样一种情况,对象是以这种方式定义的,并且父子节点都具有相同名称的函数(Overloading)。在这种情况下,执行的函数是引用类(即父(动物)类)的函数,这就是我们得到这样输出的原因。

    【讨论】:

    • 问题代码中没有被覆盖的方法。
    【解决方案3】:

    编译器根据你给它的信息决定调用哪个方法。

    这些方法都不会相互覆盖,因为它们都有不同的签名。签名由方法名称、参数数量和参数类型组成。

    这使得这个练习更容易,因为唯一决定执行哪个方法的是编译器认为每个对象和参数是什么类型。

    编译器不运行方法或构造函数。当你声明一个变量时,它只知道你告诉它什么。

    • 您声明了 Shark bruceShark anchor,因此编译器知道 bruce 和 anchor 属于 Shark 类型。因此,它选择了 Shark 类中最具体的方法:makePair(Shark s) 方法。
    • 你声明了Animal donald,所以编译器只知道唐纳德是Animal类型。您实际分配给它的内容并不重要,因为编译器没有运行该代码。编译器知道的就是你告诉它的,那就是 donald 是 Animal 类型,而该类型只有一个方法,所以调用了 makePair(Animal a) 方法。
    • 编译器知道 anchor 是 Shark 类型,但 daffy 是 Duck 类型。 Shark 声明了自己的 makePair 方法,该方法接受 Shark 类型的参数,但 daffy 参数不匹配,因此唯一可以匹配的方法是 Shark 从 Animal 继承的 makePair(Animal a) 方法。

    【讨论】:

      猜你喜欢
      • 2023-01-08
      • 2012-05-21
      • 2013-04-05
      • 2022-01-10
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      相关资源
      最近更新 更多