Reputation: 6123
I've written a method that I can use ClassName.methodName(args)
.
How can I make it so I can use methodName(args)
.
I tried monkey patching Object like so:
class Object {
def methodName(args) {
// method definition
}
}
Update:
I tried what dmahapatro said.
import static groovy.json.JsonOutput.*
Object.metaClass.outputJson = {
return println(prettyPrint(toJson(it)))
}
outputJson([:])
Return:
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]
The issue created by the edit was because Object.groovy conflicted with Groovy's Object.java. Once I renamed it to ObjectMeta (or any other non conflicting name, it worked).
Upvotes: 1
Views: 157
Reputation: 50275
Using ExpandoMetaClass
on 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")
This can also be achieved by using @Category
as below
@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')
If you want to distribute the @Category
in a jar, then include CustomizedObject
in that jar and use it wherever needed.
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
}
Note:-
One thing to catch here is, we are using metaClass
on Object
directly which can be pivotal sometimes, you should clear the metaClass
from object once you are done with it.
Upvotes: 1
Reputation: 28757
There are several possibilities that you can do. The simplest one is to use categories. In your main method or script do something like this:
use(ObjectExtender) {
startProgram();
}
And then create the ObjectExtender class like this:
class ObjectExtender {
static def methodName(Object self, Map args) {
...
}
}
As long as you are inside the control flow of the use
call, you will be able to call methodName
on any object. There are other possibilities, like creating a new metaClass for object, but I'd probably go with categories.
Upvotes: 0