2017-05-06 10 views
1

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

具体而言,我曾经可以用隐式转换为摘要的“混合”类型(例如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; }))); 
    } 
} 

回答

2

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

+0

有道理,谢谢。我会在哪里定义所说的'@:from'函数?我是否需要创建另一个摘要? –

+0

您可以在此代码中看到@:from。 https://github.com/nanjizal/triangulations/blob/master/triangulations/Vertices.hx#L125 – Justinfront

+0

试过实施这些建议,它适用于我现有的所有示例。但想出了另一个例子,在添加新摘要后,似乎不再有效。更新了我原来的问题,如果有人想看看。 –

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

(新毫无疑问 - >东西,它可能是更清洁,但基础尚未更新MAC这样Nightlies版不能玩!)

+0

你也可以创建一个数组抽象来帮助转换,但可能你仍然需要一个循环,你可以使用@:forward来获得所有正常的数组方法。 – Justinfront

0

跟进 这部作品试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

相关问题