简体   繁体   English

在Java中使用Groovy向类添加方法

[英]Adding methods to a class using Groovy in Java

I am working on a Java module that uses Groovy as a compile time dependency and I would like to add a method to my Java class Person (Like the Groovy JDK ) without writing Groovy code. 我正在研究一个使用Groovy作为编译时依赖项的Java模块,我想在不编写Groovy代码的情况下向我的Java类Person (如Groovy JDK )添加一个方法。

In Groovy I would achieve it like that 在Groovy中,我会像那样实现它

Person.meta.doSomething = { String param -> println "do something: ${param}" }

How can I do it using the Groovy API form Java? 如何使用Groovy API表单Java来完成它?

EDIT 1: 编辑1:

I have implemented the following so far and I am almost there. 到目前为止我已经实现了以下内容,我几乎就在那里。 I instantiate an Expando class for Person and register a MethodClosure that delegates the method call to a method in the class PersonDefaultMethods . 我实例化在Expando类Person并注册MethodClosure该委托方法调用的类中的方法PersonDefaultMethods

ExpandoMetaClass expando = new ExpandoMetaClass (Person.class, true, false);
expando.registerInstanceMethod ("format", new MethodClosure (new PersonDefaultMethods(), "format"));
expando.initialize ();

The PersonDefaultMethods contains the the implementation of the methods I declared in the Expando class. PersonDefaultMethods包含我在Expando类中声明的方法的实现。

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();
    }
}

When I know execute a Groovy script within this context I am able to call the format method on a Person instance but I am unable to access the delegate like I usually can using a closure. 当我知道在这个上下文中执行Groovy脚本时,我能够在Person实例上调用format方法,但是我无法像通常使用闭包那样访问delegate

EDIT 2: 编辑2:

The approach of using a closure subclass or anonymous closure class fails in my implementation. 在我的实现中,使用闭包子类或匿名闭包类的方法失败了。

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 ();

This does the job. 这样做了。 Thank you. 谢谢。

You can get the current meta class via GroovySystem.getMetaClassRegistry().getMetaClass(Person.class); 您可以通过GroovySystem.getMetaClassRegistry().getMetaClass(Person.class);获取当前的元类GroovySystem.getMetaClassRegistry().getMetaClass(Person.class); better. 更好。 But to simulate the above you need to do several things by hand Groovy does for you in the background. 但要模拟上述内容,您需要手动完成Groovy在后台为您做的几件事。

  • First of all, you will need a ExpandoMetaClass (short EMC). 首先,您需要一个ExpandoMetaClass (短EMC)。 If the metaclass from above is not an EMC, you will need to create one and register it in the registry: ExpandoMetaClass emc = new ExpandoMetaClass(Person.class) . 如果上面的元类不是EMC,则需要创建一个并在注册表中注册它: ExpandoMetaClass emc = new ExpandoMetaClass(Person.class)
  • Next you will need to call registerInstanceMethod with either a String and Closure, or a MetaMethod. 接下来,您需要使用String和Closure或MetaMethod调用registerInstanceMethod The variant above is the Closure version and will call the other one in the background. 上面的变体是Closure版本,将在后台调用另一个版本。
  • To follow the Groovy conventions you need to create a Closure subclass (maybe anonymous) with a doCall method of the Signature you want your method be. 要遵循Groovy约定,您需要使用Signature的doCall方法创建一个Closure子类(可能是匿名的)。 The String for registerInstanceMethod will be the name of the method registerInstanceMethod的字符串将是方法的名称
  • You can of course also leverage one of the existing MetaMethod subclasses (or your own one) to get there. 您当然也可以利用现有的MetaMethod子类之一(或您自己的子类)来实现目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM