我有
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 检查当前所有实现我的界面的已知类。
这样做的好方法是什么?
答案 0 :(得分:16)
重载解析在编译时而不是在Java中的执行时间完成。根据变量的编译时类型选择签名。执行时只确定覆盖。
Java等语言的常见解决方案是使用double dispatch和visitor 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覆盖它