为什么我们不能覆盖方法并将其定义为 return 原始方法的超类?
why we can't override a method and define it to return a superclass of the original method?
我目前正在学习 Java 类 和 java tutorial oracle 的对象,并且遇到了以下语句和代码。我理解这个概念,但我不知道为什么我们不能覆盖一个方法并将其定义为 return 原始方法的超类?其背后的原因是什么?有人可以启发我吗?在此先感谢您的帮助!
You can override a method and define it to return a subclass of the
original method, like this:
public Number returnANumber() {
...
}
覆盖原始方法:
public ImaginaryNumber returnANumber() {
...
}
将方法重写为 return 更 "general" class(即超级class)是没有意义的,因为在这种情况下你正在破坏returning "at least" a ImaginaryNumbe
r 的 "contract" 及其相应的功能。如果突然有人将此方法覆盖到 return 只有常规 Number
,该方法的调用者将中断,因为他们依赖于获得 ImaginaryNumber
(也许他们正在调用类似 getImaginaryPart()
这对于非虚数没有意义)。
反过来(例如returning a subclass,即更具体的class)不会破坏契约,因为subclass 至少具有与 superclass.
相同的功能
当有人编写使用 super-class 的代码时,他们只依赖于 super-class 定义的契约。
所以你可以这样写:
SuperClass instance = ...
Number num = instance.returnANumber();
现在,instance
可能是 SuperClass
的任何子 class 的实例,其中一些可能会覆盖 returnNumber()
。如果覆盖方法return是Number
的子class,它仍然return是Number
([=14的任何子class =] 仍然是 Number
),所以赋值仍然有效。如果重写方法可以 return Number
的超 class,赋值将不再有效,因此不允许。
想象一下,如果可能的话:
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!
}
}
看,这只是合同的事情。当你去咖啡店时,你希望它能卖咖啡。不符合这个约定的东西不能叫"a coffee shop":咖啡店必须卖咖啡。
它可以卖奶咖啡,因为奶咖啡仍然是咖啡。 (就像一家汽车厂只能生产丰田,因为丰田是一辆汽车,你可以像驾驶任何其他汽车一样驾驶丰田,甚至不知道它是丰田:这就是多态)。 =11=]
我目前正在学习 Java 类 和 java tutorial oracle 的对象,并且遇到了以下语句和代码。我理解这个概念,但我不知道为什么我们不能覆盖一个方法并将其定义为 return 原始方法的超类?其背后的原因是什么?有人可以启发我吗?在此先感谢您的帮助!
You can override a method and define it to return a subclass of the original method, like this:
public Number returnANumber() {
...
}
覆盖原始方法:
public ImaginaryNumber returnANumber() {
...
}
将方法重写为 return 更 "general" class(即超级class)是没有意义的,因为在这种情况下你正在破坏returning "at least" a ImaginaryNumbe
r 的 "contract" 及其相应的功能。如果突然有人将此方法覆盖到 return 只有常规 Number
,该方法的调用者将中断,因为他们依赖于获得 ImaginaryNumber
(也许他们正在调用类似 getImaginaryPart()
这对于非虚数没有意义)。
反过来(例如returning a subclass,即更具体的class)不会破坏契约,因为subclass 至少具有与 superclass.
相同的功能当有人编写使用 super-class 的代码时,他们只依赖于 super-class 定义的契约。
所以你可以这样写:
SuperClass instance = ...
Number num = instance.returnANumber();
现在,instance
可能是 SuperClass
的任何子 class 的实例,其中一些可能会覆盖 returnNumber()
。如果覆盖方法return是Number
的子class,它仍然return是Number
([=14的任何子class =] 仍然是 Number
),所以赋值仍然有效。如果重写方法可以 return Number
的超 class,赋值将不再有效,因此不允许。
想象一下,如果可能的话:
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!
}
}
看,这只是合同的事情。当你去咖啡店时,你希望它能卖咖啡。不符合这个约定的东西不能叫"a coffee shop":咖啡店必须卖咖啡。 它可以卖奶咖啡,因为奶咖啡仍然是咖啡。 (就像一家汽车厂只能生产丰田,因为丰田是一辆汽车,你可以像驾驶任何其他汽车一样驾驶丰田,甚至不知道它是丰田:这就是多态)。 =11=]