简而言之,您在Java中重载了“覆盖”的意义:-)。让我们假装别人写了Animal
类:(稍微改写它,不改变任何语义,但是为了演示一个好习惯)。我们也将假设Animal
编译并运行良好:
public class Animal {
public static void main(String args[]) {
Animal a = new Animal(); // yes, Animal, no Horse yet.
a.eat();
}
///// Animal's private methods, you should not look here
private void eat() {
System.out.println("animal eating");
}
///// Animal's private methods, you should not look here
}
这是一个很好的Java编码的做法,因为Animal
类的作者不希望你,代码的读者,要真正了解什么Animal
“私人企业。
接下来,您看的public static void main
方法,并正确推断在此定义了一个名为eat()
的方法。在这一点上,下面的搁置:
- 像Java中的任何其他类一样,
Animal
延伸Object
。
- 您看看
Object
的公共(和受保护)方法,并发现没有像eat()
这样的方法。鉴于Animal
编译得很好,你可以推断eat
ing必须是Animal
的私人业务! Animal
无法编译。因此,在不看Animal
的私人业务的情况下,您可以推断Animal
类中有eat()
方法,即私人!
现在,让我们说你的目的是要创建一个名为Horse
另一种动物作为一个专门Animal
,并给它吃的特殊行为。你想知道你是而不是要去查看Java Lang Spec并找出所有这些规则,只需使用extends
关键字并完成它。然后出现Horse
的第一个版本。然而地方,它是更好地阐明你的覆盖的意图你听说过(这是一件事,你现在是肯定的 - 你想覆盖eat
荷兰国际集团的Horse
行为):
class Horse extends Animal {
@Override
public void eat() {
System.out.println("Horse eating");
}
}
权;你添加标签@Override
。无可否认,这总是一个好主意,但增加了一些措词(这是一个很好的做法,有几个原因,我们不会进入这里)。
尝试编译Horse.java
,你会看到:
Error:(21, 5) java: method does not override or implement a
method from a supertype
因此,知道Java编程语言比我们更好的编译器,告诉我们,其实,不覆盖或实施一种在超类型中声明的方法。
现在Java中重写的处理变得更加清晰了。由于我们应该仅仅覆盖那些被设计用于重写的行为,即公共方法和受保护的方法,所以我们应该小心如何编写超类。在这种情况下,无意中,显然设计用于扩展的超类Animal
使得子类不可能覆盖行为!
即使我们删除了@Override
标签以摆脱编译器错误/警告的技术性,我们不一定会做正确的事情,因为在运行时,正如您观察到的那样,其签名匹配的非预期方法获取调用。这更糟糕。
嘛,你不解释它的正上方。 'a'的声明类型是Animal,而不是Horse,而Animal.eat()是私有的,所以它不能被覆盖,所以它不能被多态地调用。子类方法将被调用,如果它覆盖基类的方法类,但它不,所以... –
@JBNizet,是的,但他们为什么动物类吃方法被称为,我无法理解。是因为我们有参考动物类吗?但是我们有Horse类的对象。那为什么要调用Animal类的方法? –
所有编译器都知道'a'是它是一个Animal:这是它的声明类型。所以编译器在Animal中寻找eat()方法。它找到一个,它是私有的,所以它调用这个方法。并且由于它不可能被覆盖,因此正在调用Animal.eat()。 –