假设我想在Haxe中创建一个带有闪存ByteArray
和Array
的通用内联函数。
@:generic public static inline function WriteArray<T:(UInt, Int, Float)>(ba:ByteArray, array:Array<T>):Void
{
if (array == null)
{
ba.writeInt(-1);
}
else
{
ba.writeInt(array.length);
for (i in 0...array.length)
{
// here is where I have a problem
// ba.writeUnsignedInt(array[i]); if T is UInt
// ba.writeDouble(array[i]); if T is Float
// ba.writeInt(array[i]); if T is Int
}
}
}
所以,我需要一些方法让每个生成的函数在那里使用不同的行。此代码需要具有高性能,因此不能选择对类型进行运行时检查。我也无法传递哪个写入函数用作参数(writeFunc:T->Void
)b / c我们当前正在编译为Flash,而Flash每次引用时都会创建一个MethodClosure
对象函数,垃圾收集器不能很好地处理它们(无论函数是否内联,都会发生这种情况)。我也试过使用宏,但你不能在宏内部的flash库中使用任何东西(我有类似的函数用于编写flash向量,我们仍然使用flash的ByteArray
实现)。我希望有一种方法可以在编译时获得T
,但我发现的只有${type}
而且我认为你不能有条件地使用它。
那么,有没有办法让这个函数在ByteArray
上调用正确的write方法而不创建对该函数的引用?它不一定要使用@:generic
,但我认为约束会有所帮助。其他实施想法也将受到欢迎。现在我只有3个相同功能的版本,而c / p代码只是让我呕吐在我的嘴里。
答案 0 :(得分:4)
我也试过使用宏,但你不能在宏内的flash库中使用任何东西
这并非完全正确:您实际上无法在宏中使用 Flash API,但您可以生成使用它的代码。您只需确保不将其添加为文件顶部的import
- 语句,而是使用完全限定名称(flash.utils.ByteArray
)。
这是一个简单的例子:
import haxe.macro.Context;
import haxe.macro.Expr.Access;
import haxe.macro.Expr.FieldType;
class Macro {
public static function build() {
var fields = Context.getBuildFields();
fields.push({
name: "byteArray",
access: [Access.APublic, Access.AStatic],
kind: FieldType.FVar(macro:flash.utils.ByteArray, null),
pos: Context.currentPos(),
});
return fields;
}
}
...生成:
public static var byteArray:flash.utils.ByteArray;