ndsc-account 2020-01-13 01:27 采纳率: 100%
浏览 442
已采纳

Java中指向子类的父类对象调用子类重载的方法,传入指向子类对象的父类引用,为什么最终还是调用了父类的方法?

Dog类实现了Animal接口,Animal a = new Dog(); 创建子类对象,a指向的应该是一个Dog类的对象,a.bark(d); 调用的应该是Dog重载的bark方法才对,可为什么最终调用的还是接口Animal的方法呢。

public interface Animal {
    default void bark(Animal a) {
        System.out.println("Animal");
    }
}

public class Dog implements Animal {
    // Overload
    public void bark(Dog d) {
        System.out.println("Dog");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        Dog d = new Dog();
        a.bark(a); // Animal
        a.bark(d); // Animal

        d.bark(a); // Animal
        d.bark(d); // Dog
    }
}
  • 写回答

6条回答 默认 最新

  • 关注
    1. a是一个Animal类型引用,调用方法时,编译器会先去Animal类中的虚函数表中找有没有可以调用的方法。编译器找到Animal中的bark方法,而bark并没有被Dog实现,且Animal中的bark方法参数类型为Animal,而Dog为Animal的实现类,所以函数可以使用,于是编译器偷了个懒就不去Animal类的虚函数表中去匹配方法了,所以a.bark(d),调用的是接口中的方法。

    2. 而d是一个Dog类型引用。编译器会先去Dog类的虚函数表中找有没有可以调用的方法,找到Dog中的bark方法和Animal中的bark方法,因为参数d为Dog类型,固根据参数匹配原则选择Dog类中的bark方法。

    3. 总的来说,接口类型的引用,优先使用接口中没被实现且可以用的方法。在Animal类的虚函数表中,只有Animal的bark方法地址,没有Dog中的bark方法地址。

    4. 深究可以去看看虚函数表,不过这个概念只在C++中存在,而java和C++本是同根生。

    5. 原创手打,忘采纳。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • 农夫丶果园 2020-01-13 09:14
    关注

    可能是因为这俩不是一个方法吧 ,他们的方法参数不一样 , 我感觉你把Override注释掉是不是因为编辑器给你提示报错说这里不能使用Override , 因为他们不是同一个方法,你把方法的参数都去掉就行了, 反正这个方法的参数你也没有用到

    评论
  • 一名剑客 2020-01-13 09:46
    关注

    因为方法重写没有成功,输入参数可以放大但不能缩小,你把public void bark(Dog d) 中的Dog改成Animal就可以了

    评论
  • Ricardo·M·Smile 2020-01-13 09:49
    关注

    Animal a = new Dog(); 是dog实现了Animal 类的接口 调用的自然是 Animal的, 为什么bark()可以传递Dog 应该是dog是 Animal的实现类(Animal a = new Dog(); )。,没有更好的解释,如果有大神可以通知我一下。

    评论
  • threenewbee 2020-01-13 10:43
    关注

    Java语言不支持重写方法的协变(Contravariant)
    也就是public void bark(Dog d)只能定义为
    public void bark(Animal d)
    你非要那么写,则两个bark是不同的方法,不构成覆盖,只能是重载而已。

    评论
  • 「已注销」 2020-01-13 11:52
    关注

    楼上回答的很正确,同时补充一下如果你要是想a也调用子类的方法应该再次使用向下转型Dog a1 = (Dog)a;这个时候调用的是子类方法

    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 如何通过求后验分布求得样本中属于两种物种其中一种的概率?
  • ¥15 q从常量变成sin函数,怎么改写python代码?
  • ¥15 图论编程问题,有可以指导的吗
  • ¥15 DEA的CCR模型画图
  • ¥15 请假各位一个关于安卓车机的问题
  • ¥15 光谱仪怎么看这样的透射谱
  • ¥15 pyqt5 如何实现输入框输入关键词,下拉框显示模糊查询返回的结果?
  • ¥20 fluent模拟,可以燃烧和相变同时模拟吗?
  • ¥50 海康摄像头,C#如何识别车牌号码和抓取JPG
  • ¥15 yolov5 pt转engine的问题