假设我已经扩展了现有代码,但也避免尽可能地更改代码。
在这个代码周围有一个接收某种类型的方法。
Engine.method(Base b)
现在,我想扩展此功能。所以我将Base扩展为一个名为Derived的类型,它包含了我需要的更多数据,并且我还实现了另一个接收Derived类型并使用它做一些不同的方法。
Engine.method(Derived d)
但我不想将原来的呼叫改为“方法”。我以某种方式设法通过使用标志来实现正确的类型(Base或Derived),但由于原始调用正在使用Base,因此我的新方法将不会被调用。
Base b = null;
if(flag) {
b = new Derived()
} else{
b = new Base()
}
Engine.method(b)
问题是现在我的Engine.method(Derived d)不会被调用。我通过使用铸造
解决了这个问题if(flag)
Engine.method((Derived)b)
但这是错误和愚蠢的。有什么建议吗?
我总能做到:
if(flag) {
Engine.methodForBase(new Base())
} else{
Engine.methodForDerived(new Derived())
}
但你能想到更好的东西吗?
由于
答案 0 :(得分:4)
这是因为Java使用单一调度。这结束意味着在您的情况下,调用的方法取决于引用的类型“b”,它是Base,而不是“b”所包含的实例的类型。因此,将始终调用方法xpto。(Base b)。
你真的必须施展或使用你写的最后一种方法。
答案 1 :(得分:3)
写下这个:
class Engine {
public static void method(Base argument) {
if (argument instanceof Derived) {
// ...
}
else {
// ...
}
}
}
但可能,您应该扩展您的Engine
类以允许更多的多态性,例如做这样的事情:
interface Engine<T extends Base> {
void method(T argument);
}
并且Base
和Derived
的实施方式如下:
class BaseEngine implements Engine<Base> {
@Override
public void method(Base argument) { ... }
}
class DerivedEngine implements Engine<Derived> {
@Override
public void method(Derived argument) { ... }
}
答案 2 :(得分:0)
为什么不简单地用正确类型的参数调用方法?
Base b = null;
if (flag) {
Derived d = new Derived()
Engine.method(d); // so the correct method will be used for Derived
b = d;
} else{
b = new Base()
Engine.method(b)
}
您还可以考虑重复使用method(Base b)
:
public void method(Derived d) {
method((Base)b);
...
}