在 Java 中使用 Groovy 添加方法到 class
Adding methods to a class using Groovy in Java
我正在开发一个使用 Groovy 作为编译时依赖项的 Java 模块,我想向我的 Java class Person
(类似于 Groovy JDK)而无需编写 Groovy 代码。
在Groovy我会这样实现
Person.meta.doSomething = { String param -> println "do something: ${param}" }
如何使用 Groovy API 形式 Java?
编辑 1:
到目前为止,我已经实施了以下内容,我快完成了。我为 Person
实例化一个 Expando class 并注册一个 MethodClosure
将方法调用委托给 class PersonDefaultMethods
.
中的方法
ExpandoMetaClass expando = new ExpandoMetaClass (Person.class, true, false);
expando.registerInstanceMethod ("format", new MethodClosure (new PersonDefaultMethods(), "format"));
expando.initialize ();
PersonDefaultMethods
包含我在 Expando class 中声明的方法的实现。
public class PersonDefaultMethods {
public String format(String format) {
return this.toString(); // this one gets called
}
public String format(Person self, String format) { // but I want this method to be called
return self.getFirstname() + " " + self.getLastname();
}
}
当我知道在此上下文中执行 Groovy 脚本时,我可以在 Person
实例上调用 format
方法,但我无法访问 delegate
就像我通常可以使用闭包一样。
编辑 2:
使用闭包子class或匿名闭包class的方法在我的实现中失败了。
ExpandoMetaClass expando = new ExpandoMetaClass(Person.class, true, false);
expando.registerInstanceMethod("format", new Closure(this) {
@Override
public Object call(Object arguments) {
return super.call(arguments);
}
@Override
public Class[] getParameterTypes () {
return new Class[] { String.class};
}
});
expando.initialize ();
这样就可以了。谢谢。
您可以通过 GroovySystem.getMetaClassRegistry().getMetaClass(Person.class);
更好地获取当前元数据 class。但是要模拟上面的内容,你需要手动做几件事 Groovy 在后台为你做。
- 首先,你需要一个
ExpandoMetaClass
(简称EMC)。如果上面的 metaclass 不是 EMC,您需要创建一个并在注册表中注册:ExpandoMetaClass emc = new ExpandoMetaClass(Person.class)
。
- 接下来您需要使用字符串和闭包或元方法调用
registerInstanceMethod
。上面的变体是Closure版本,会在后台调用另一个。
- 要遵循 Groovy 约定,您需要创建一个 Closure subclass(可能是匿名的),并使用您想要的 Signature 的 doCall 方法。
registerInstanceMethod
的字符串将是方法的名称
- 您当然也可以利用现有的 MetaMethod 子class之一(或您自己的子)来达到目的。
我正在开发一个使用 Groovy 作为编译时依赖项的 Java 模块,我想向我的 Java class Person
(类似于 Groovy JDK)而无需编写 Groovy 代码。
在Groovy我会这样实现
Person.meta.doSomething = { String param -> println "do something: ${param}" }
如何使用 Groovy API 形式 Java?
编辑 1:
到目前为止,我已经实施了以下内容,我快完成了。我为 Person
实例化一个 Expando class 并注册一个 MethodClosure
将方法调用委托给 class PersonDefaultMethods
.
ExpandoMetaClass expando = new ExpandoMetaClass (Person.class, true, false);
expando.registerInstanceMethod ("format", new MethodClosure (new PersonDefaultMethods(), "format"));
expando.initialize ();
PersonDefaultMethods
包含我在 Expando class 中声明的方法的实现。
public class PersonDefaultMethods {
public String format(String format) {
return this.toString(); // this one gets called
}
public String format(Person self, String format) { // but I want this method to be called
return self.getFirstname() + " " + self.getLastname();
}
}
当我知道在此上下文中执行 Groovy 脚本时,我可以在 Person
实例上调用 format
方法,但我无法访问 delegate
就像我通常可以使用闭包一样。
编辑 2:
使用闭包子class或匿名闭包class的方法在我的实现中失败了。
ExpandoMetaClass expando = new ExpandoMetaClass(Person.class, true, false);
expando.registerInstanceMethod("format", new Closure(this) {
@Override
public Object call(Object arguments) {
return super.call(arguments);
}
@Override
public Class[] getParameterTypes () {
return new Class[] { String.class};
}
});
expando.initialize ();
这样就可以了。谢谢。
您可以通过 GroovySystem.getMetaClassRegistry().getMetaClass(Person.class);
更好地获取当前元数据 class。但是要模拟上面的内容,你需要手动做几件事 Groovy 在后台为你做。
- 首先,你需要一个
ExpandoMetaClass
(简称EMC)。如果上面的 metaclass 不是 EMC,您需要创建一个并在注册表中注册:ExpandoMetaClass emc = new ExpandoMetaClass(Person.class)
。 - 接下来您需要使用字符串和闭包或元方法调用
registerInstanceMethod
。上面的变体是Closure版本,会在后台调用另一个。 - 要遵循 Groovy 约定,您需要创建一个 Closure subclass(可能是匿名的),并使用您想要的 Signature 的 doCall 方法。
registerInstanceMethod
的字符串将是方法的名称 - 您当然也可以利用现有的 MetaMethod 子class之一(或您自己的子)来达到目的。