非类型类型参数

时间:2018-10-11 14:03:40

标签: haxe

如果我的类仅在代码中使用的某些常量不同,该怎么办?是否有可能在不花费运行时间的情况下实现一个通用实现?

这里是例子(有点长...)

@:enum abstract Param(Int) {
    var foo = 0;
    var bar = 1;
}

class WorkBase {

    public function new() {}

    private inline function work_impl(p: Param): Void {

        if(p == foo) {
            trace('foo');
        }
        else {
            trace('bar');
        }
    }

    public function work(): Void {

    }
}

class WorkFoo extends WorkBase{
    override public function work(): Void {
        work_impl(foo);
    }
}

class WorkBar extends WorkBase {
    override public function work(): Void {
        work_impl(bar);
    }
}

class Test {

    public static function main() {
        var workFoo = new WorkFoo();
        var workBar = new WorkBar();
        workFoo.work();
        workBar.work();
    }
}

使用-D analyzer-optimize进行编译后,我们将看到WorkFoo.work()WorkBar.work()函数已经过优化,并且仅包含与Param值之一匹配的代码分支。在现实生活中,work_impl()中有很多这样的比较,并且它们都已被优化。很好。

但是,如果我不想手动创建WorkFooWorkBar,该怎么办。是否可以做这样的事情:

@:generic
class WorkBase<PARAM> {
    private inline function work_impl(p: Param): Void {
        ...
    }

    public function work(): Void {
        work_impl(PARAM);
    }
}

我知道最接近的是const-type-parameter。但是我觉得通用构建不是一个不错的选择。

1 个答案:

答案 0 :(得分:2)

  

我知道最接近的是const-type-parameter。但是我觉得通用构建不是一个不错的选择。

可以在不使用@:genericBuild的情况下使用常量类型参数-与@:generic结合使用的常量类型参数足以实现所需的优化:

@:enum abstract Param(Int) from Int {
    var foo = 0;
    var bar = 1;
}

@:generic class Work<@:const PARAM:Int> {
    public function new() {}

    public function work():Void {
        if (PARAM == foo) {
            trace('foo');
        } else {
            trace('bar');
        }
    }
}

class Main {
    public static function main() {
        var workFoo = new Work<0>();
        var workBar = new Work<1>();
        workFoo.work();
        workBar.work();
    }
}

由于@:generic,为每个常量值生成一个类,例如在JS上,输出如下所示:

var Work_$0 = function() {
};
Work_$0.prototype = {
    work: function() {
        console.log("source/Main.hx:11:","foo");
    }
};
var Work_$1 = function() {
};
Work_$1.prototype = {
    work: function() {
        console.log("source/Main.hx:13:","bar");
    }
};

请注意,由于某些原因,此示例在Haxe 3.4.7中失败,并显示“约束检查失败”,但在Haxe 4 Preview 4和更高版本中可以正常使用。另一个限制是new Work<Param.foo>()new Work<foo>()都不起作用-您需要传递实际的常数值。