向全局名称空间添加方法

时间:2013-06-17 18:53:05

标签: groovy

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

我如何才能使用methodName(args)

我试过像这样修补对象:

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

更新

我尝试了dmahapatro所说的。

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(或任何其他非冲突的名称,它就有效)。

2 个答案:

答案 0 :(得分:1)

ExpandoMetaClass上使用Object

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中包含CustomizedObject并在需要的地方使用它。

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
}

注意: -
这里要注意的一点是,我们直接在metaClass使用Object这有时可能很关键,一旦完成,您应该从对象中清除metaClass

答案 1 :(得分:0)

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

use(ObjectExtender) {
  startProgram();
}

然后像这样创建ObjectExtender类:

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

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