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));
}
}
此处:
我试图将一种类型的数组视为另一种(抽象)类型的数组。当我使用抽象的基础类型时,它工作正常。但是当我尝试使用另一种类型(使用 @: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));
}
}
此处: