铸造一个泛型类型中HAXE

问题描述:

修订问题:铸造一个泛型类型中HAXE

我已经做了一些挖掘和工作过劳伦斯·泰勒的回答。我几乎在那里,但它似乎不能与递归包装。这里有一个更新的可运行的代码片段,它显示了问题(这次使用我的类,因为我不想重新定义一切)

New runnable code sample

具体地,请注意,{t : 3}(正确地)结合到一个公平的第一时间,但同时{t : {t : 3}}(也正确地)结合到一个公平,嵌套{t : 3}结合到nonequitable。这怎么可能是相同的对象t1t2首次结合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);} 
} 

从本质上讲,我有一堆类(其中AB只是两个),其中一些落实自己SelfReferringInterface(如B一样),和其他人没有实现它。

然后,我有一个通用类,它可以包含任何类型:

class GenericClass<T> { 
    private var t : T; 
    public function new(t : T) {this.t = t;} 
} 

我想一个方法添加到GenericClass<T>,如果它的TSelfReferringInterface的实施将调用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(..)在所有可能的?我可以控制所有的课程,但我试图避免改变AB以使其成为可能。必要时我可以添加到SelfReferringInterfaceGenericClass。想法?


我已经做了一些挖掘,它似乎(由于协方差useages),我宁愿SelfReferringInterface<X>的typedef而非接口。我仍然坚持实施doStuffOrTrace(..),但也许这会打开新的途径?

+0

我想尝试的一件事是明确输入包装的输出,对泛型类型的类型解析有一些含糊之处。 因为应该隐式调用抽象构造函数,所以你不应该首先明确地调用wrap,并且可以完全避免Equatable的问题。 –

最佳写具有这两种情况下的枚举,包裹在一个抽象的及写入@:从功能每种情况下,和使用,作为输入到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

+0

我可以给一个镜头..你可以添加一个有效使用@:从语法的例子吗?这对我来说是新的 – Mshnik

+0

修正了与可运行代码链接的答案。 –

+0

非常感谢!我使用你的代码工作了90%,但我在递归调用中遇到了一些麻烦。看到我更新的问题 – Mshnik

你可以使用Std.is确定T的类型和其转换成SelfReferringInterface实施doStuffOrTrace:

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