Haxe摘要 - 在使用@:from?

时间:2017-05-06 18:04:41

标签: casting haxe

我正在尝试将一种类型的数组视为另一种(抽象)类型的数组。当我使用抽象的底层类型时,它工作正常。但是当我尝试使用其他类型(使用@:from关键字定义)进行隐式转换时,我会遇到构建失败。

如果我使用明确的cast,它会起作用,但我想知道 - 有什么方法可以解决这个问题吗?

在下面的示例中,我得到了构建失败Array<Int> should be Array<StringAbstract>

class Test {
    static function main() {
        var test:String = "Hello World";
        print(test); //this works

        var testArr:Array<String> = ["Hello", "World"];
        printArray(testArr); //this works (using underlying type)

        var testInt:Int = 10;
        print(testInt); //this works

        var testIntArr:Array<Int> = [1, 2, 3];
        printArray(cast testIntArr);  //this works (explicit cast)
        printArray(testIntArr);  //build failure (using @:from)
    }

    static function print(s:StringAbstract) {
        trace(s);
    }

    static function printArray(arr:Array<StringAbstract>) {
        trace(arr);
    }
}

abstract StringAbstract(String) from String to String {
    inline function new(s:String) {
        this = s;
    }

    @:from
    static public function fromInt(i:Int) {
        return new StringAbstract(Std.string(i));
    }
}

跟进

根据Gama11和Justinfront的建议,我定义了一个抽象来将数组转换为抽象类型的数组。但是现在我遇到了另一个问题 - 一旦我从函数声明了@:它就会破坏以前工作的代码。

具体来说,我曾经能够使用隐式转换为摘要的“混合”类型来调用我的函数(例如printArray([1, "2", 3]);)。

但是,只要我添加@:from函数来转换来自不同类型的数组(在这种情况下为Array<Int>),该功能就会崩溃,错误为Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>

好奇,如果有人知道为什么会这样(例如:https://try.haxe.org/#65D03)。

class Test {
    static function main() {        
        var testMixedArr:Array<StringAbstract> = [1, "2", 3];
        printArray(testMixedArr); //this works
        printArray([1, "2", 3]); //this doesn't work, unless I remove "fromIntArray" function
    }

    static function printArray(arr:StringAbstractArray) {trace(arr);}
}


abstract StringAbstractArray(Array<StringAbstract>) from Array<StringAbstract> to Array<StringAbstract> {
    inline function new(s:Array<StringAbstract>) {
        this = s;
    }

    @:from
    static public function fromIntArray(intArr:Array<Int>) {
        return new StringAbstractArray(Lambda.array( Lambda.map( intArr, function(i: Int):StringAbstract { 
            return i; } )));
    }
}

3 个答案:

答案 0 :(得分:2)

唯一的解决方法是定义一个@:from的显式Array<Int>函数。 Variance section of the Haxe Manual解释了这一点的原因。它有一个很好的例子,说明在这种情况下,转换如何导致在运行时执行不安全的代码(而不是被编译器捕获)。

答案 1 :(得分:1)

printArray( Lambda.array( Lambda.map( testIntArr, function(v: Int):StringAbstract { 
            return v; } )));

(毫无疑问,新的 - &gt;东西可能更干净但是基础还没有更新mac nightlies所以无法播放!)

答案 2 :(得分:-1)

跟进 这适用于尝试haxe,你确定你甚至需要这样做吗?

 class Test {
    static function main() {        
        var testMixedArr:Array<StringAbstract> = [1, "2", 3];
        printArray(testMixedArr); //this works
        printArray(new StringAbstractArray([1, "2", 3]));
    }

    static function printArray(arr:StringAbstractArray) {
        trace(arr);
    }

}


 abstract StringAbstractArray(Array<StringAbstract>) from Array<StringAbstract> to Array<StringAbstract> {
    inline public function new(s:Array<StringAbstract>) {
        this = s;
    }

    @:from
    static public function fromIntArray(intArr:Array<Int>) {
    return new StringAbstractArray(Lambda.array( Lambda.map( intArr, function(i: Int):StringAbstract { 
        return i; } )));
    }
}


abstract StringAbstract(String) from String to String {
    inline function new(s:String) {
       this = s;
    }

    @:from
    static function fromInt(i:Int) {
        return new StringAbstract(Std.string(i));
    }
}

这里:

http://try-haxe.mrcdk.com/#ED866