Showing posts with label duck-typing. Show all posts
Showing posts with label duck-typing. Show all posts

Tuesday, December 4, 2007

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:


// 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)
See? We create "it", then add quacking behaviour, and then test it. Easy. This prints
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.