我正在尝试将一种类型的数组视为另一种(抽象)类型的数组。当我使用抽象的底层类型时,它工作正常。但是当我尝试使用其他类型(使用@: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; } )));
}
}
答案 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));
}
}
这里: