metaClass tips

MetaClass fun… A metaClass is a way to add a method-like statement to an existing Class at runtime. I don’t know another way to say it really. For the JavaScript gurus out there, this is the same as the prototype if you rewrote the code I provide swapping metaClass with prototype they’d be the same thing… assuming the objects existed in JavaScript.

Anyway, so, what’s the real benefit here?

Well, sometimes I have convenience methods or things I want to do on Java classes that I don’t have access to, so I’ll work them out as a metaClass then load them up with my Groovy runtime. Or I use this in my code when I want to test something out, but not touch the Java objects or Groovy Objects at this time.

It gives me the power to work with an Object on my terms not its terms. Programming and Development, to me, is about making something do what I want and not about being constrained… I’m such a rebel!

Adding metaClass functions to a class isn’t a big deal. You have to remember that your changes are only available during the runtime. If you don’t call out to start those, then nothing will happen except exceptions.

So I’m going to add a convenience method to the File object so that I can pass in an object, the File will be read and automatically set the values of the properties in the object.

ObjectX {
String firstName
String lastName
}

names.properties
firstName=bob
lastName=kelso

now for the metaClass magic:
I want to call
new File(“”).parseProperties(instanceOfObjectX)

the props file will be read in and put the values where they go
so let’s start with the basics we’re going to create a parseProperties Closure on the File metaClass
File.metaClass.parseProperties = {}

we also know that we’re going to take an object with properties we want to set:
File.metaClass.parseProperties = {object ->

}

we know that we want to read the file that we’ve told it:
File.metaClass.parseProperties = {object ->
delegate.eachLine {

}
}

Uh oh, delegate? delegate is the calling File object. so the new File(“names.properties”) is the delegate, it’s the one that we want to do our parseProperties on kind of like saying this

So, what’s next? Well we need to take the line, make sure it’s valid, make sure it doesn’t start with the common properties comment, a # sign, after that we want to put the values into the object, right?

File.metaClass.parseProperties = {object ->
delegate.eachLine {
if (!it.startsWith(“#”) && it) {
def tmp = it.split(“=”)
object.setProperty(tmp[0],tmp[1])
}
}
}

That is it… with object.setProperty we have a name value pairing that does the work… so now our instance of ObjectX will have the values set as if you had done a lot of reflection code.

now you only need the following:
def instanceOfObjectX = new ObjectX()
new File(“./names.properties”).parseProperties(instanceOfObjectX)

the results will be
instanceOfObjectX.firstName //bob
instanceOfObjectX.lastName //kelso

one final note… what if we wanted to load the object without an instance of the File object:

Well, we can not, but we can make it a static Closure of the File object so the following is possible:
File.parseProperties(“names.properties”, instanceOfObjectX)

There are some minor changes that need to be made to our metaClass Closure we wrote, but nothing major:
File.metaClass.‘static’.parseProperties = {fileName, object ->
new File(fileName).eachLine {
if (!it.startsWith(“#”) && it) {
def tmp = it.split(“=”)
object.setProperty(tmp[0],tmp[1])
}
}
}

You can see that I only made three changes to the code outlined in bold that’s it.

enjoy many days of metaClassing your Groovy Objects

One Reply to “metaClass tips”

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 )

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.

%d bloggers like this: