[英]Polymorphism in Overloaded and Overridden Methods
我们来看看这个简单的Java代码:
public class Animal {
public void eat() {
System.out.println("Generic Animal Eating Generically");
}
}
public class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay ");
}
public void eat(String s) {
System.out.println("Horse eating " + s);
}
}
我试图找出三个eat()方法的哪个版本将运行。 现在,当我输入
Animal a = new Animal();
a.eat();
输出是“Generic Animal Eating Generically”,这是完全可以理解的。
输入时会发生同样的事情:
Horse h = new Horse();
h.eat();
输出是“马吃干草”,这也是完全合乎逻辑的。
这就是让我感到困惑的地方。 当我输入:
Animal ah = new Horse();
ah.eat();
我明白了:
Horse eating hay
我希望编译器从Animal类引用调用eat()方法,而不是Horse对象引用。
所以我的问题是,当我有一个引用对象类型的泛型引用变量类型时,我怎么能确定编译器将调用哪个方法(如下所示:Animal horse = new Horse();
我希望编译器从Animal类引用调用eat()方法,而不是Horse对象引用。
我们首先纠正这个说法。 变量ah
是Animal
类型的引用,语句new Horse()
创建一个Horse
类型的实例并将其分配给Animal
引用。
既然术语是明确的,那么这种行为是可以预期的,并被称为runtype-polymorphism或动态方法dispatch。 在编译时, eat()
基于类型为Animal
的引用类型进行解析,但在运行时,将调用的方法基于实例类型Horse
。
当我有一个引用对象类型的泛型引用变量类型时,我怎么能确定编译器要调用哪个方法
您可以按照以下简单步骤操作:
ah.eat()
调用方法eat
。 Animal ah = new Horse()
,引用类型是Animal
,它是父类 Animal ah = new Horse()
,实例类型是Horse
,它是子类。 如果满足上述所有条件,则您将查看runtype多态,并将调用子类中的方法。 在任何其他场景中,将根据引用类型解析要调用的方法。
理解子类从父类继承方法也是值得的。 可以说你从Horse
类中删除了public void eat()
方法,你不再覆盖 eat()
方法; 然而,在Horse
的public void eat(String s)
方法仍被称为从Animal
过载继承的eat
方法。 接下来,让我们在Animal
添加一个public void eat(String s)
方法。 通过此添加,您现在正在重载 Animal
的eat
方法并在Horse
类中覆盖它。 无论您如何更改代码,上述4个步骤将始终帮助您确定将调用哪个方法。
这在Java中称为动态绑定。 使用explicite对象类型而不是引用类型。
无法使用单个方法调用overriden super方法和覆盖方法,请参阅: 如何调用超类的重写方法 。 你可以为你的马添加一个方法,它将调用委托给动物,如:
public class Horse extends Animal {
public void animalEat() {
super.eat();
}
public void eat() {
System.out.println("Horse eating hay ");
}
}
这是因为方法覆盖而发生的。 在方法重写中,引用类型无关紧要,重要的是对象类型。 Animal ah
只是对象的引用而实际对象是Horse
类型。 因此,将调用Horse
的方法而不是引用类型Animal
的方法。
哦,新关键字将创建给定类的实例...
new Horse();
现在Horse类已经是Animal的孩子了。 所以下面将实例化。
public void eat() {
System.out.println("Horse eating hay ");
}
现在您尝试将该对象存储在Animal的对象中。 这意味着Object Of Horse存储在Animal的Object中。
Animal ah = new Horse();
所以在Animal的对象中,已经存储了Horse的成员。 这就是编译器打印子类方法值的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.