Groovy 将方法添加到全局名称空间

Groovy 将方法添加到全局名称空间,groovy,Groovy,我已经编写了一个可以使用ClassName.methodName(args)的方法 如何使用methodName(args) 我试着用猴子修补对象,如下所示: class Object { def methodName(args) { // method definition } } 更新: 我试过德马哈帕特罗说的话 import static groovy.json.JsonOutput.* Object.metaClass.outputJson = {

我已经编写了一个可以使用
ClassName.methodName(args)
的方法

如何使用
methodName(args)

我试着用猴子修补对象,如下所示:

class Object {
    def methodName(args) {
        // method definition
    }
}
更新:

我试过德马哈帕特罗说的话

import static groovy.json.JsonOutput.*

Object.metaClass.outputJson = {
    return println(prettyPrint(toJson(it)))
}

outputJson([:])
返回:

Caught: groovy.lang.MissingMethodException: No signature of method: Object.outputJson() is applicable for argument types: (java.util.LinkedHashMap) values: [[:]]
Possible solutions: outputJson(), outputJson(java.lang.Object)
groovy.lang.MissingMethodException: No signature of method: Object.outputJson() is applicable for argument types: (java.util.LinkedHashMap) values: [[:]]
Possible solutions: outputJson(), outputJson(java.lang.Object)
    at Object.run(Object.groovy:7)
[Finished in 2.1s]

编辑产生的问题是因为Object.groovy与groovy的Object.java冲突。一旦我将它重命名为ObjectMeta(或任何其他不冲突的名称,它就起作用了)。

有几种可能。最简单的方法是使用类别。在主方法或脚本中,执行以下操作:

use(ObjectExtender) {
  startProgram();
}
class ObjectExtender {
  static def methodName(Object self, Map args) {
    ...
  }
}
然后创建ObjectExtender类,如下所示:

use(ObjectExtender) {
  startProgram();
}
class ObjectExtender {
  static def methodName(Object self, Map args) {
    ...
  }
}

只要您在
use
调用的控制流中,就可以对任何对象调用
methodName
。还有其他的可能性,比如为object创建一个新的元类,但我可能会选择categories。

有几种可能性可以做到。最简单的方法是使用类别。在主方法或脚本中,执行以下操作:

use(ObjectExtender) {
  startProgram();
}
class ObjectExtender {
  static def methodName(Object self, Map args) {
    ...
  }
}
然后创建ObjectExtender类,如下所示:

use(ObjectExtender) {
  startProgram();
}
class ObjectExtender {
  static def methodName(Object self, Map args) {
    ...
  }
}

只要您在
use
调用的控制流中,就可以对任何对象调用
methodName
。还有其他的可能性,比如为object创建一个新的元类,但我可能会选择categories。

object上使用
ExpandoMetaClass

Object.metaClass.printsHello = {
    return it
}

assert "Hello" == printsHello("Hello")
assert "Hello" == 'ABC'.printsHello("Hello")
assert "Hello" == 123.printsHello("Hello")
assert "Hello" == new Object().printsHello("Hello")

class A{
    Integer a
}

assert "Hello" == new A(a: 10).printsHello("Hello")
这也可以通过使用下面的
@Category
来实现

@Category(Object) class CustomizedObject{
    def printsHello(String str){
        return str
    }
}

String.mixin CustomizedObject
assert 'Hello' == 'ABC'.printsHello('Hello')

Integer.mixin CustomizedObject
assert 'Hello' == 123.printsHello('Hello')

BigInteger.mixin CustomizedObject
assert 'Hello' == 123G.printsHello('Hello')

@Mixin(CustomizedObject) //Compile Time Mixin
class A{
}

assert 'Hello' == new A().printsHello('Hello')
如果要在jar中分发
@Category
,请在该jar中包含
定制对象
,并在需要时使用它

import static groovy.json.JsonOutput.*

Object.metaClass.outputJson = {
    return prettyPrint(toJson(it))
}

println outputJson([a: 1, b: 2, c: 3])

//Prints:
{
    "a": 1,
    "b": 2,
    "c": 3
}
注意:-

这里需要注意的一件事是,我们直接在
对象上使用
元类
,这有时可能是关键的,您应该在使用完对象后从对象中清除
元类

对象
上使用
ExpandoMetaClass

Object.metaClass.printsHello = {
    return it
}

assert "Hello" == printsHello("Hello")
assert "Hello" == 'ABC'.printsHello("Hello")
assert "Hello" == 123.printsHello("Hello")
assert "Hello" == new Object().printsHello("Hello")

class A{
    Integer a
}

assert "Hello" == new A(a: 10).printsHello("Hello")
这也可以通过使用下面的
@Category
来实现

@Category(Object) class CustomizedObject{
    def printsHello(String str){
        return str
    }
}

String.mixin CustomizedObject
assert 'Hello' == 'ABC'.printsHello('Hello')

Integer.mixin CustomizedObject
assert 'Hello' == 123.printsHello('Hello')

BigInteger.mixin CustomizedObject
assert 'Hello' == 123G.printsHello('Hello')

@Mixin(CustomizedObject) //Compile Time Mixin
class A{
}

assert 'Hello' == new A().printsHello('Hello')
如果要在jar中分发
@Category
,请在该jar中包含
定制对象
,并在需要时使用它

import static groovy.json.JsonOutput.*

Object.metaClass.outputJson = {
    return prettyPrint(toJson(it))
}

println outputJson([a: 1, b: 2, c: 3])

//Prints:
{
    "a": 1,
    "b": 2,
    "c": 3
}
注意:-

这里需要注意的一件事是,我们直接在
对象上使用
元类
,这有时是关键的,您应该在使用完对象后从对象中清除
元类

理想情况下,我希望分发一个jar,以便自动执行此操作。我想如果我使用ObjectExtender,我必须要求每个人都这样做。我的假设正确吗?类别中的方法不应该是静态的吗?@dmahapatro是的,应该是。谢谢你指出这一点。理想情况下,我想分发一个罐子,这样就可以自动完成。我想如果我使用ObjectExtender,我必须要求每个人都这样做。我的假设正确吗?类别中的方法不应该是静态的吗?@dmahapatro是的,应该是。谢谢你指出这一点。改变了答案你是用同样的剧本做的吗?该解决方案看起来很棒,但我尝试通过在
对象.metaClass
中设置方法来测试它,但它抱怨它只接受
java.lang.Object
。是的,我在groovy控制台中将其作为单个groovy脚本运行。您还可以使用@Category(正如@Andrew所提到的)。您还可以在需要时创建@Category和@Mixin来完成以上步骤,由于一切都是Java extends
Object
@SunnyJuneja,因此它可以毫不费力地工作。请看一下我关于如何使用
@Category
并在jar中分发功能的更新。感谢您迄今为止的帮助,dmahapatro,但该类别要求我将其绑定到一个类。就像你做的
new A().printsHello('Hello')
但是我不想只做
printsHello('Hello')
。有没有办法让第一个版本生效?你看到我关于我的问题的更新了吗?让我们看看你是用同样的脚本来做的吗?该解决方案看起来很棒,但我尝试通过在
对象.metaClass
中设置方法来测试它,但它抱怨它只接受
java.lang.Object
。是的,我在groovy控制台中将其作为单个groovy脚本运行。您还可以使用@Category(正如@Andrew所提到的)。您还可以在需要时创建@Category和@Mixin来完成以上步骤,由于一切都是Java extends
Object
@SunnyJuneja,因此它可以毫不费力地工作。请看一下我关于如何使用
@Category
并在jar中分发功能的更新。感谢您迄今为止的帮助,dmahapatro,但该类别要求我将其绑定到一个类。就像你做的
new A().printsHello('Hello')
但是我不想只做
printsHello('Hello')
。有没有办法让第一个版本生效?你看到我关于我的问题的更新了吗?让我们
返回println(prettyPrint(toJson(it))
不起作用。仅返回
prettyPrint
JSON
returnprettyprint(toJson(it))
您还需要让闭包接受一个参数:Object.metaclass.outputJson={args->returnprettyprint(toJson(args))}
returnprintln(prettyPrint(toJson(it))
不起作用。仅返回
prettyPrint
JSON
returnprettyprint(toJson(it))
您还需要让闭包接受一个参数:Object.metaclass.outputJson={args->returnprettyprint(toJson(args))}