考虑我在Java中有一个抽象类的情况;
public abstract class Foo
{
public abstract int myOperation();
}
现在,它的一些子类可能会覆盖myOperation,就像这样;
class A extends Foo
{
public int myOperation()
{
// Do stuff
}
}
但是如果一个子类想要返回一些其他数据类型,如;
class A extends Foo
{
public Object myOperation()
{
// Do stuff
}
}
我希望方法名称相同,以保持设计完整,以便客户端不必选择要调用的方法。除了使用一个是空实现或使用Object作为返回类型的单独方法之外,还有其他解决方法吗?或者这是OO设计的一个严重错误的例子?
我听说过C ++中的Covariant返回类型,并想知道Java是否还有其他机制。
我也可以在这里自由使用界面。
答案 0 :(得分:8)
你做不到。既不使用继承,也不使用接口。这将是编译器错误,因此您根本无法运行程序。
您可以返回java.lang.Object
并返回您想要的任何对象。如果需要返回基元,可以返回其对象包装器。
答案 1 :(得分:7)
“这是OO设计的一个严重错误的例子”是的。你不能这样做。
答案 2 :(得分:5)
Java具有共变量返回类型,但返回类型必须更具体,而不是更具体。如果父类中的方法返回int
,那么它的所有子类型也必须这样做,否则这种方法的调用者并不真正知道它所获得的类型。
Foo foo = new A()
int i = foo.method();
如果method()返回除int
之外的任何内容,则此语句不再有意义。
当你能做的时候,如果超类中的方法返回Object
而一个dervice类返回Number
那么两者的子类都可以返回Integer
答案 3 :(得分:3)
当您使用返回类型(即,变量)时,可以使用不同的数据类型。当您使用原始数据类型时,您无法更改它。
如果超类方法是任何派生数据类型,则在子类返回类型中过度删除可以是相同的派生数据类型或子类派生数据类型。
答案 4 :(得分:2)
这是不可能的,因为在抽象类中声明的方法定义了一个契约:它返回一个int。所有实施都必须遵守此合同。如果你这样做会发生什么:
Foo foo = new A();
int i = foo.myOperation();
它会中断,因为myOperation不会返回int
。这就是为什么不允许它。
但允许的是以下内容:
public abstract class Foo {
public abstract Object myOperation();
}
public class A extends Foo {
@Override
public String myOperation() {
return "some string";
}
}
在这种情况下,合同得到尊重。该方法必须返回一个Object,它返回一个String,一个String 是一个Object。
答案 5 :(得分:2)
你不能这样做,因为它会违反Foo
的合同。
A a = new A();
someUtilityMethod(a);
...
void someUtilityMethod(Foo foo){
int i = foo.myOperation(); // This would break
}
这个原则被称为Liskov substitution principle,它是构建OO的 基础。