Haxe abstracts - 我可以在使用@:from 时隐式转换数组吗?

Haxe abstracts - Can I implicitly cast an array when using @:from?

我试图将一种类型的数组视为另一种(抽象)类型的数组。当我使用抽象的基础类型时,它工作正常。但是当我尝试使用另一种类型(使用 @: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 的建议,我定义了一个抽象来将数组转换为我的抽象类型的数组。但是现在我 运行 遇到了一个不同的问题 - 一旦我声明了一个 @:from 函数,它就会破坏以前工作的代码。

具体来说,我曾经能够使用隐式转换为抽象的 "mixed" 类型(例如 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; } )));
    }
}

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

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

(毫无疑问,有了新的 -> 东西,它可能会更干净,但基础尚未更新 mac 每晚,所以不能玩!)

跟进 这适用于 try 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