So I just read a post where a kind of cool debug was posted by Jochen Theodorou (blackdrag) The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/
Anyway, I thought this was a great example of something that could be done with a metaClass change. I want to debug something so I do object.debug()
You’re asking, and oh yes, I went there.
So, what is there to remember? You can’t do this with a base object and expect it to work across them all… that’s it… so it then either becomes a PITA (pain in the a$$) or you always call Object.debug(yourObject, NameOfObjectItsEqualTo)… so I’ll show you both
First, calling statically. Remember in the last post, I taught you about two ways to add to the metaClass with:
Object.metaClass and Object.metaClass.'static'
Wondering why static is in quotes. static is a keyword in Java and Groovy… so to trick the compiler and runtime, put quotes around it now we can use it however we want.
So, here is everything for an Object.debug and object.debug (or new Object().debug if you prefer)
//static impl Object.metaClass.'static'.debug = {obj, eq -> def clazz = obj.getClass() def s = {it.name == eq} println "-"*30 println clazz println "-"*30 println clazz.methods.findAll(s) println "-"*30 println clazz.declaredMethods.findAll(s) println "-"*30 println obj.getMetaClass().methods.findAll(s) println "-"*30 println obj.getMetaClass().metaMethods.findAll(s) println "-"*30 }
//non static impl
Object.metaClass.debug = {obj, eq ->
Object.debug(obj, eq)
}
//non static impl relying on the delegat call
Object.metaClass.debug = {eq ->
Object.debug(delegate, eq)
}
def b = “Bob”
//works
Object.debug(b, “String”)
doesn’t work
b.debug(“String”)
//blows up
“Bob”.debug(b, “String”)
So what happened there… just blows up?!
Well, the issue is that Object has both static and instance access to debug, but String doesn’t. What was that? Did I hear you start stomping your feet? That’s right, metaClasses don’t affect higher nor lower objects even those that extend or implement from them.
So let’s fix that:
Add this to below the Object declarations we had above:
String.metaClass.'static'.debug = {obj, eq -> Object.debug(obj, eq) }
String.metaClass.debug = {obj, eq ->
Object.debug(obj, eq)
}
String.metaClass.debug = {eq ->
Object.debug(delegate, eq)
}
Now run and you should get something like this:
------------------------------ class java.lang.String ------------------------------ [] ------------------------------ [] ------------------------------ [] ------------------------------ [] ------------------------------
So, not exactly what we wanted, but I’m sure you don’t really want to call “bob”.debug(“String”) or “bob”.debug(“bob”, “String”) so I’m sure that Object.debug(“bob”, “String”) is just fine.
I’ll work on solving the Object inheritance issue with invokeMethod in the next segment.
Thanx to Jochen for something so simple to debug with.
One Reply to “metaClass things to remember”