metaClass things to remember

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.