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