2015-09-02 53 views
4

我正在研究将Groovy用作编译时间依赖项的Java模块,并且希望在不编写Groovy代码的情况下向我的Java类Person(如Groovy JDK)添加一个方法。在Java中使用Groovy添加方法

在Groovy我我该怎么办使用Groovy的API形式的Java它将实现它像

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

编辑1:

我已实施至今下面,我几乎没有。我为Person实例化一个Expando类,并注册一个MethodClosure,该方法调用委托给类PersonDefaultMethods中的方法。

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

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

当我知道这种情况下我能够调用format方法上Person实例中执行Groovy脚本,但我无法访问delegate像我平时可以使用封闭。

编辑2:

使用封闭子类或匿名closure类的方法我在执行失败。

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

这样做的工作。谢谢。

+0

即使你可以得到这个工作,是不是你的代码最终会被查找和注册表调用混乱? Java不适合这种实例扩展。因此Groovy –

+0

我绝对同意你的看法。我尝试使用这种方法的唯一原因是我的公司使用Eclipse(不提供Groovy支持),如果我开始将Groovy类放入其工作空间中,该项目将不再生成...我知道这是一个糟糕的情况,但我不能改变它(还)。 – saw303

+1

re:“无法访问委托”。在MethodClosure中,委托/所有者用于方法调用,在这里是PersonDefaultMethods,所以它不会像这样工作。你将需要一个Closure子类。 – blackdrag

回答

2

您可以通过GroovySystem.getMetaClassRegistry().getMetaClass(Person.class);获得更好的当前元类。但要模拟上述内容,您需要手动完成Groovy在后台为您做的几件事情。

  • 首先,您需要一个ExpandoMetaClass(简称EMC)。如果上面的元类不是EMC,则需要创建一个并在注册表中注册它:ExpandoMetaClass emc = new ExpandoMetaClass(Person.class)
  • 接下来,您需要使用String和Closure或MetaMethod调用registerInstanceMethod。上面的变体是Closure版本,将在后台调用另一个。
  • 要遵循Groovy约定,您需要创建一个Closure子类(可能是匿名的),并使用您希望使用该方法的Signature的doCall方法。 registerInstanceMethod的字符串将是方法的名称
  • 您当然也可以利用现有的MetaMethod子类之一(或您自己的)来达到目的。
+0

感谢您的解释。我应用了它,但现在我遇到了一个异常(请参阅更新后的问题) – saw303