Zen and Groovy's Expando
In the past, I had trouble remembering the concept behind Groovy's Expando class. I knew it wasn't difficult but it was elusive. Perhaps I was distracted by the groovy-ness of the name.
In a recent training class with Jeff Brown, I was struck by a metaphor.
Readers of CtJ know the old refrain of dynamic-typing:
If it walks like a duck and quacks like a duck, I would call it a duck.
In other words, if "it" can provide the desired behaviour (e.g. quacking), then it can pass for a duck, in so far as a dynamic language cares. Cool beans.
Well, in Groovy, the
Expando class is an empty "it"! It is a container for various behaviours, to which we can add stuff. Check out this code sample:See? We create "it", then add quacking behaviour, and then test it. Easy. This prints
// tests the incoming, purported "duck" to see
// if "it" really quacks
def duckTester = { duck ->
duck.quack()
}
////////////////////////// Main
// create "it"... it cannot quack -- yet
def it = new Expando()
// add quacking
it.quack = { println "quack!" }
// call test: "if it quacks like a duck"
duckTester.call(it)
quack!to the console.
Question: does anyone know the origin of the
Expando name? I've searched but not found it.
ps. A less glamorous way of thinking about it is that
Expando is a map of methods and attributes. I'm sticking with ducks and it.pps.
Expando's are especially useful for mocking objects in unit-tests.