我正在编写一个需要类来实现 clone() 方法的接口。我对此的天真做法是这样的:
public interface ISolvableGame {
function clone():ISolvableGame;
//...
}
别处:
public class MyGame implements ISolvableGame {
public function clone():MyGame {
// ...
}
}
我原以为这种签名是合法的,因为MyGame.clone()
返回了一个实现 ISolvableGame 的类的实例,在我看来这满足了接口中的约定。但是,像上面这样的代码会产生一个编译错误,指的是MyGame.clone()
具有与接口中指定的签名不同的签名这一事实。
因此,我的问题是,如果实现的方法必须与接口中的签名完全匹配,我该如何制作需要克隆方法的接口?显然,使界面更具体没有任何意义。但是,如果我使实现的方法不那么具体(即,如果我键入MyGame.clone()
为返回ISolvableGame
),该克隆方法的其他用户将不再知道他们得到了什么。
我是否需要两个版本的克隆方法,一个是ISolvableGame
为了满足接口而键入的,另一个是MyGame
为了在类中使用而键入的?还是有更好的方法?
注意:我正在使用 ActionScript3(一种实现 ECMA4 规范的类 Java 语言)。我将其标记为与语言无关,因为假设 AS3 在处理接口的方式上并不是独一无二的。但是如果我上面的示例代码可以在其他语言中工作,那么我的问题可能特定于我的语言。
更新: 我突然想到检查我的语言的核心库是如何处理这个问题的。例如,有一个IEventDispatcher
接口,它定义了一个方法dispatch():Event
- 所以任何调度子类的类Event
都无法实现IEventDispatcher
,这最终与我的问题相似。
核心库通过让此类类继承自一个类来处理这个问题,该类EventDispatcher
的存在是为了实现IEventDispatcher
。因此获得了编译时类型安全,但代价是首先会淡化使用接口的意义,因为人们通常更喜欢接口来避免继承带来的问题。
我在想我的选择是:
- 最终依赖继承,就像核心库所做的那样
- 实现 Frederik 描述的两种方法,具有不同的名称
- 正如 James 所描述的那样牺牲编译时类型安全
回答:最后,我选择让接口指定一个cloneToSolvable
方法 - 即,接口指定一个克隆到接口类型的方法,并且实现类必须具有该方法以及它们的任何更具体类型的克隆方法可能有。在我看来,这似乎是最不令人不快的选择。