Chapter 7
[ 179 ]
then:
"""<root>
<level1>
<level2>
</level2>
</level1>
</root>""" == output()
In order to illustrate the builder mechanism shown in the previous code snippet,
we are conveniently ignoring any parameter passing, and assuming that args just
contains a first parameter of the type Closure. However, this short example does
illustrate method pretending through the invokeMethod(), and method relaying by
assigning delegate.
ExpandoMetaClasses
We briefly touched on metaclasses when building our Twitter DSL in Chapter 4,
The Groovy Language. In the coming example, we've used String.metaClass to
dynamically add a method to the String class for Twitter searching. Let's look at
what is happening here:
String.metaClass.search = { Closure c ->
GeeTwitter.search(delegate,c)
}
From the earlier section on expandos, we understand how an Expando allows us
to dynamically add a property to a class. That's all that is happening here. In the
preceding code, we are dynamically adding a property to MetaClass for String in
the same way as we added properties to Expando. This property happens to be a
Closure, and the object happens to be the MetaClass of String, so it has the effect
of adding a new method to the String class.
Adding a regular property to MetaClass can be achieved in the same way as
with expandos. There is only a single MetaClass per Groovy or Java class, so
this is useful only if we have a new property that is relevant across all instances
of a class. In practice, this will rarely happen. Apart from adding properties and
methods, there are a whole bunch of other interesting things that we can do with
ExpandoMetaClass. We will go through a selection of them here.