在Haxe中转换为通用类型

时间:2016-08-05 14:45:04

标签: generics haxe

更新的问题:

我已经完成了一些挖掘并完成了劳伦斯泰勒的回答。我几乎就在那里,但它似乎无法与递归包装一起使用。这是一个更新的可运行代码片段,显示了问题(这次使用我的类,因为我不想重新定义所有内容)

New runnable code sample

具体来说,注意{t : 3}(正确)第一次绑定到一个公平,但是{t : {t : 3}}(也正确)绑定到一个公平,嵌套{t : 3}绑定到一个不公平的。相同的对象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那样) ,以及其他没有实现它的人。

然后我有一个可以包装任何类型的Generic类:

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。想法?

我已经做了一些挖掘,看起来(由于协方差使用)我宁愿SelfReferringInterface<X> typedef 而不是接口。我仍然坚持实施doStuffOrTrace(..),但也许这开辟了新的途径?

2 个答案:

答案 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