我目前正在学习来自java tutorial oracle的Java类和对象,并且遇到了以下语句和代码。我理解这个概念,但我不知道为什么我们不能覆盖一个方法并定义它来返回原始方法的超类?它背后的原因是什么?有人可以赐教吗?在此先感谢您的帮助!
您可以覆盖方法并定义它以返回该类的子类 原始方法,如下:
public Number returnANumber() {
...
}
覆盖原始方法:
public ImaginaryNumber returnANumber() {
...
}
答案 0 :(得分:4)
想象一下是否有可能:
public class CarFactory {
Car giveMeACar() { ... };
}
public class SpecialCarFactory extends CarFactory {
@Override
Object giveMeACar() {
return "hello world";
}
)
public class Driver {
void drive() {
CarFactory carFactory = new SpecialCarFactory();
Car car = carFactory.giveMeACar();
// err, wait, sorry, can't do that.
// This car factory, despite its name, doesn't produce cars.
// It produces objects, and I've heard they're just
// "hello world" strings. Good luck driving a "hello world"
// string on a highway!
}
}
看,这只是合同的事情。当你去咖啡馆,你希望它出售咖啡。如果不符合这个合同,有些东西不能被称为“咖啡店”:咖啡店必须卖咖啡。 它可以出售挤奶咖啡,因为挤奶咖啡仍然是咖啡。 (就像汽车厂只能生产丰田汽车一样,因为丰田汽车是一辆汽车,你可以驾驶丰田汽车,就像任何其他汽车一样,甚至不知道它是丰田:那就是多态性。)
答案 1 :(得分:0)
覆盖一个返回更“通用”类(即超类)的方法是没有意义的,因为在这种情况下,你打破了“至少”返回ImaginaryNumbe
r的“契约”具有相应的功能。如果突然有人认为这种方法只返回常规Number
,那么该方法的调用者就会因为依赖于获取ImaginaryNumber
(也许他们正在调用类似getImaginaryPart()
之类的内容而中断对非想象的数字有意义。)
反过来说(例如,返回一个子类,即一个更具体的类)不会破坏契约,因为子类至少具有与超类相同的功能。
答案 2 :(得分:0)
当有人编写使用超类的代码时,他们只依赖于超类定义的契约。
所以你可以这样写:
SuperClass instance = ...
Number num = instance.returnANumber();
现在,instance
可能是SuperClass
的任何子类的实例,其中一些可能会覆盖returnNumber()
。如果重写方法返回Number
的子类,它仍会返回Number
(Number
的任何子类仍然是Number
),因此赋值是还是有效。如果重写方法可以返回超级Number
,则该赋值将不再有效,因此不允许。