更新的问题:
我已经完成了一些挖掘并完成了劳伦斯泰勒的回答。我几乎就在那里,但它似乎无法与递归包装一起使用。这是一个更新的可运行代码片段,显示了问题(这次使用我的类,因为我不想重新定义所有内容)
具体来说,注意{t : 3}
(正确)第一次绑定到一个公平,但是{t : {t : 3}}
(也正确)绑定到一个公平,嵌套{t : 3}
绑定到一个不公平的。相同的对象t1
和t2
第一次绑定到Equitable
怎么可能,但第二次NonEquitable
?
问题v1:
我正在通过Haxe,并已达到一个简化到这一点:
interface SelfReferringInterface<X> {
public function doStuff(x : X) : Void;
}
class A {
private var x : Int;
public function new(x : Int){this.x = x;}
public function toString() {return Std.string(x);}
}
class B implements SelfReferringInterface<B> {
private var x : Int;
public function new (x : Int){this.x = x;}
public function doStuff(b : B) {
trace(this + " and " + b);
}
public function toString() { return Std.string(x);}
}
基本上,我有一堆类(其中A
和B
只有两个),其中一些自己实现SelfReferringInterface
(如B
那样) ,以及其他没有实现它的人。
然后我有一个可以包装任何类型的Generic类:
class GenericClass<T> {
private var t : T;
public function new(t : T) {this.t = t;}
}
我想向GenericClass<T>
添加一个方法,如果T
是SelfReferringInterface
的实现,则调用doStuff,否则会有其他默认行为:
class GenericClass<T> {
private var t : T;
public function new(t : T) {this.t = t;}
public function doStuffOrTrace(t2 : T) {
//if t instanceof SelfReferringClass, call t.doStuff(t2)
//otherwise call trace(t) and ignore t2
}
}
以下测试方法执行以下操作。
class Test {
static function main() {
new GenericClass<A>(new A(3)).doStuffOrTrace(new A(4));//Expect 3
new GenericClass<B>(new B(1)).doStuffOrTrace(new B(2));//Expect 1 and 2
}
}
是否尽可能实施doStuffOrTrace(..)
?我控制了所有课程,但我试图避免改变A
和B
以使其成为可能。我可以根据需要添加到SelfReferringInterface
或GenericClass
。想法?
我已经做了一些挖掘,看起来(由于协方差使用)我宁愿SelfReferringInterface<X>
是 typedef 而不是接口。我仍然坚持实施doStuffOrTrace(..)
,但也许这开辟了新的途径?
答案 0 :(得分:4)
Best写一个包含两种情况的枚举,将它包装在一个摘要中,并从每个case的函数中编写@:并将其用作doStuffOrTrace的输入。
在正常使用中,调用该函数将导致调用正确的抽象构造函数,然后您可以在内部使用开关来区分。
*编辑
@:from static public function fromHasInterface<T>(v:SelfReferringInterface<T>):HasInterfaceOrNot<T>{
return THasInterface(v);
}
enum HasInterfaceOrNotT<T>{
THasInterface(v:SelfReferringInterface<T>);
THasNotInterface(v:Dynamic);
}
查看正在运行的代码here
答案 1 :(得分:1)
您可以使用Std.is实现doStuffOrTrace来确定t的类型并将其强制转换为SelfReferringInterface:
public function doStuffOrTrace(t2 : T) {
if(Std.is(t, SelfReferringInterface)){
var castedT = cast(t, SelfReferringInterface<Dynamic>);
castedT.doStuff(t2);
}else{
trace(t);
}
}
问题是你从来没有明确地使用toString方法,所以它将被编译器(dce)剥离,trace(t)将输出'[object]'
您可以通过添加@:将元数据添加到方法来防止这种情况发生
您无法修改A和B,可以使用-dce no
或-dce std
编译器标志禁用dce
以下是try.haxe代码段:http://try.haxe.org/#40402