Java方法覆盖/接口问题

时间:2009-07-09 16:27:02

标签: java interface

我有

interface FooI
class FooA implements FooI
class FooB implements FooI
class FooC implements FooI

我写了一个类“Handler”,它有以下方法

static double handle(FooA f)
static double handle(FooB f)
static double handle(FooI f)

我有以下功能:

void caller(FooI f)
{
    Handler.handle(f);
}

f只是被称为实现FooI的类。但是f是FooA的一个实例

不是调用FooA的方法,而是调用FooI的方法。

当我使用f.getClass()。getName()时,我得到了正确的类名(FooA)。

我很困惑,因为我期待最适合的方法被调用,即FooA的方法。

我想使用FooI方法作为后备来处理可以在以后实现的类,并且我还想处理f而没有我正在做的一个大功能 instanceof 检查当前所有实现我的界面的已知类。

这样做的好方法是什么?

6 个答案:

答案 0 :(得分:16)

重载解析在编译时而不是在Java中的执行时间完成。根据变量的编译时类型选择签名。执行时只确定覆盖

Java等语言的常见解决方案是使用double dispatchvisitor pattern

就我个人而言,我并不是一个忠实的粉丝。我宁愿尝试设计自己的方式。当然,这并不总是可行的,但至少值得尝试。

答案 1 :(得分:3)

您希望JVM在运行时找到最佳拟合方法,但实际上并不会发生这种情况。相反,在编译期间选择要调用的方法,此时唯一已知的信息是f是实现FooI的类。

解决该问题的最佳方法是避免检查实例,可能是将“handle”方法移动到FooA,FooB,FooI类中。

答案 2 :(得分:1)

我不确切知道您的设计是什么,但是“处理”功能可能会更好地放在您的具体FooI实现中吗?

答案 3 :(得分:1)

Java使用引用类型解析在编译时调用哪个方法,在您的示例中为FooI - 如果您考虑它,这是有意义的因为引用类型是它真正必须在编译时继续进行的。

您的Handler类不handle(FooI f),因此就编译器而言,没有有效的handle方法可以调用。

答案 4 :(得分:0)

你不应该使用静态方法,静态方法服从其他规则而非非最终实例方法

答案 5 :(得分:0)

您可以使用处理程序实现将您的界面转换为抽象类。然后你实现它,FooA和FooB覆盖它