🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
类型构建宏和表达式宏在很多方面是不同的: * 它们不返回表达式,而是一个数组或者类字段。它们的返回类型必须显式设置为 Array<haxe.macro.Expr.Field> 。 * 它们的上下文环境(第9.1节)没有局部方法也没有局部变量。 * 它们的额上下文环境有构建字段,可以从 haxe.macro.Context.getBuildFields() 获得。 * 它们不会被直接调用,但是是一个类或者枚举声明上的 @:build 或者 @:autoBuild 元数据(第6.9节)的一个参数。 如下的例子演示了类型构建。注意,它被分成两个文件是有原因的:如果一个模块包含一个宏函数,它也必须类型化到 macro 上下文。 这对类型构建宏来说经常是一个问题,因为要构建的类型只能在它的不完整阶段被加载,在构建宏运行之前。我们建议总是定义类型构建宏到它们自己的模块。 ~~~ import haxe.macro.Context; import haxe.macro.Expr; class TypeBuildingMacro { macro static public function build(fieldName:String):Array<Field> { var fields = Context.getBuildFields(); var newField = { name: fieldName, doc: null, meta: [], access: [AStatic, APublic], kind: FVar(macro : String, macro "my default"), pos: Context.currentPos() }; fields.push(newField); return fields; } } ~~~ ~~~ @:build(TypeBuildingMacro.build("myFunc")) class Main { static public function main() { trace(Main.myFunc); // my default } } ~~~ TypeBuildingMacro 的构建方法执行三步: 1. 它使用 Context.getBuildFields() 获得构建字段。 2. 它使用 funcNace 宏参数作为字段名声明一个新的 haxe.macro.expr.Field 字段。这个字段是一个 String变量默认值为 “my default”(来自于 kind 字段),而且是 public static 的(来自于 access 字段)。 3. 它添加新的字段到构建的字段数组,并返回它。 这个宏是Main 类上 @:build 元数据的参数。一旦这个类型被需要的,编译器就做以下事: 1. 它解析模块文件,包含类字段。 2. 它设置类型,包含它和其它类型通过继承和接口产生的关系。 3. 它根据 @:build 元数据 执行类型构建宏。 4. 它使用被类型构建宏返回的字段继续如常类型化类。 这允许在一个类型构建宏中随意添加和修改类字段。在我们的例子中,宏被调用,使用了一个 myFunc 参数,使 Main.myFunc 成为一个有效的字段访问。 如果一个类型构建宏不应修改任何内容,宏可以返回null 。这指示编译器没有刻意的改变,更好的是返回 Context.getBuildFields() 。