[英]Why does Java call the overridden method even when object is upcasted?
我有以下课程:
public abstract class Animal
{
private String species;
public Animal(String ll)
{
species = ll;
}
public abstract void speak();
public String toString()
{
return "Species: " + species;
}
}
第二课:
public class Raven extends Animal
{
String name;
public Raven(String emri)
{
super("Raven");
name = emri;
}
public void speak()
{
System.out.println("krra krra");
}
public String toString()
{
return super.toString() + "\nName : "+ name ;
}
}
和测试类:
public class TestAnimals
{
public static void main(String args[])
{
Raven blabla = new Raven("Ziosh");
Animal a = blabla;
System.out.println(a.toString());
}
}
当我执行测试类时,我得到:
Species: Raven
Name: Ziosh
我不明白的是,为什么Java使用“new”toString()方法,即使我们将Raven对象“upcast”为Animal? 谢谢。
因为这就是多态性的全部内容:您可以在不知道对象的实际具体类型的情况下调用对象的方法,并且将调用在此具体类型中定义的适当方法。
这就像真实的物体一样:如果我给你一辆车,即使你不知道它实际上是一辆混合动力汽车,当你驾驶它时,汽车的行为就像一辆混合动力汽车。
在您的示例中, a
和blabla
是对同一对象的两个引用,它是一个Raven
实例。 所以这个对象*说* s和* toString *就像一个乌鸦。
当你在java中调用一个方法时,即使它被强制转换为超类型,它总是会查找调用次数最多的方法。
来自http://docs.oracle.com/javase/tutorial/java/IandI/override.html
隐藏静态方法和覆盖实例方法之间的区别具有重要意义:
- 被调用的重写实例方法的版本是子类中的版本。
- 被调用的隐藏静态方法的版本取决于它是从超类还是从子类调用的。
Raven blabla = new Raven("Ziosh"); Animal a = blabla;
在这里, a
和blabla
引用完全相同的对象,您可以通过以下方式确认:
System.out.println(a == blabla);
// prints "true"
因此, a
真的是一个Raven
,所以它自然会像Raven
一样说话,即使你把它标记为Animal
。
从人的角度考虑另一种解释。 让实现在子类的对象上执行实际上可能非常危险。 想象一下Bicycle
课程,以及更专业的BicycleWithLittleWheels
。 关于后者的事情,小轮子是非常脆弱的,如果你试图骑得太快,它们可能会破裂。 如果你让某人骑自行车就好像是一辆普通的自行车,完全明显的小轮子,他可能会打破它。 按照类似的逻辑,你可能不应该像大锤一样使用高精度牙科钻。
这就是为什么,直观地说,你不应该让一个专门的对象被视为更一般的形式。 当然,在某些情况下,使用专门的对象可能是有意义的,就好像它是更通用的东西,但并非总是如此。 编译器如何将安全案例与不安全案件区分开来? 那太难了。 所以为了保持安全,语言不会让你这样做。
Java总是使用该帖子中描述的实例方法 : java override方法调用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.