我试图用Haxe中的宏来制造一些黑暗魔法,我有一个名为Entity
的类,我想添加一个包含static
和private
修饰符的池:
Pool.hx
package exp;
class Pool<T> {
public function new(clazz:Class<T>) {
}
}
Entity.hx
package exp;
@:build(exp.PoolBuilder.build())
class Entity {
public function new(){}
}
PoolBuilder.hx
package exp;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
class PoolBuilder {
static public macro function build() : Array<Field> {
var fields = Context.getBuildFields();
var clazz = Context.getLocalClass();
var typePath = { name:"Pool", pack:["exp"], params: [TPType(TPath({name: "Entity", pack: ["exp"]}))] }
var pool = macro new $typePath(/* clazz? */);
fields.push({
name: "_pool",
access: [APrivate, AStatic],
pos: Context.currentPos(),
kind: FVar(macro: exp.Pool, pool)
});
return fields;
}
}
我对typePath
参数有问题,并将Class<T>
作为参数传递给构造函数。编译器显示此错误:
exp/Entity.hx:3:字符1-7 : exp.Pool类型参数的无效数目 exp/Entity.hx:4:第4-6行:在该类中定义
有人知道怎么解决吗?
发布于 2018-01-27 12:44:07
手动构建这样的字段有些繁琐--我建议您使用类具体化,在这里您可以将字段表示为常规的Haxe代码:
macro class {
static var _pool = new Pool(/* clazz */);
}
这完全绕过了“类型参数的无效数量”问题--只需让类型推断在new Pool()
中完成并省略类型参数。
构造函数调用的参数当然是变量,所以我们仍然需要使用一些表达物化。exp.Entity
是一个字段表达式,所以我们必须使用$p{}
。通过将clazz.pack
和clazz.name
相结合,我们可以构造它所需的类型路径。
class PoolBuilder {
static public macro function build():Array<Field> {
var fields = Context.getBuildFields();
var clazz = Context.getLocalClass().get();
var path = clazz.pack.concat([clazz.name]); // ["exp", "Entity"]
var extraFields = (macro class {
static var _pool = new Pool($p{path});
}).fields;
return fields.concat(extraFields);
}
}
这将生成以下代码(可以在exp/Entity.dump
和-D dump=pretty
中看到):
static var _pool:exp.Pool<exp.Entity> = new exp.Pool(exp.Entity);
发布于 2018-01-27 14:31:02
如果您喜欢通过fields.push({...})
添加字段而不是使用类具体化,则可以在FVar(null, pool)
中使用null
作为类型来触发类型推断。
static public macro function build() : Array<Field> {
var fields = Context.getBuildFields();
var clazz = Context.getLocalClass().get();
var path = clazz.pack.concat([clazz.name]); // ["exp", "Entity"]
var pool = macro new exp.Pool($p{path});
fields.push({
name: "_pool",
access: [APrivate, AStatic],
pos: Context.currentPos(),
kind: FVar(null, pool)
});
return fields;
}
这是为path
使用@gama11 11技巧。这将生成与@ same 11答案完全相同的代码(并且可以以相同的方式检查)。
https://stackoverflow.com/questions/48475603
复制相似问题