首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Haxe宏实例化带有参数的类

使用Haxe宏实例化带有参数的类
EN

Stack Overflow用户
提问于 2018-01-27 12:04:20
回答 2查看 538关注 0票数 6

我试图用Haxe中的宏来制造一些黑暗魔法,我有一个名为Entity的类,我想添加一个包含staticprivate修饰符的池:

Pool.hx

代码语言:javascript
运行
复制
package exp;

class Pool<T> {
    public function new(clazz:Class<T>) {
        
    }
}

Entity.hx

代码语言:javascript
运行
复制
package exp;

@:build(exp.PoolBuilder.build())
class Entity {
    public function new(){}
}

PoolBuilder.hx

代码语言:javascript
运行
复制
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行:在该类中定义

有人知道怎么解决吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-27 12:44:07

手动构建这样的字段有些繁琐--我建议您使用类具体化,在这里您可以将字段表示为常规的Haxe代码:

代码语言:javascript
运行
复制
macro class {
    static var _pool = new Pool(/* clazz */);
}

这完全绕过了“类型参数的无效数量”问题--只需让类型推断在new Pool()中完成并省略类型参数。

构造函数调用的参数当然是变量,所以我们仍然需要使用一些表达物化exp.Entity是一个字段表达式,所以我们必须使用$p{}。通过将clazz.packclazz.name相结合,我们可以构造它所需的类型路径。

代码语言:javascript
运行
复制
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中看到):

代码语言:javascript
运行
复制
static var _pool:exp.Pool<exp.Entity> = new exp.Pool(exp.Entity);
票数 6
EN

Stack Overflow用户

发布于 2018-01-27 14:31:02

如果您喜欢通过fields.push({...})添加字段而不是使用类具体化,则可以在FVar(null, pool)中使用null作为类型来触发类型推断。

代码语言:javascript
运行
复制
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答案完全相同的代码(并且可以以相同的方式检查)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48475603

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档