Saturday, October 3, 2009

Groovy Goodness: Mixin Functionality to Classes

In a previous blog post we learned how to use Categories to add functionality to existing class. We had to use the use keyword to define a block in which the Category was valid. But we can also add new functionality with the @Mixin compile-time annotation or at runtime with the mixin() method (GDK extension to Class).

class Pirate {
    def talk(text) {
        "Aargh, walk the plank. ${text}"

// Compile time mixin to Talk class. This add all
// methods from Pirate to Talk.
class Talk {}

assert 'Aargh, walk the plank. Give me a bottle of rum.' == new Talk().talk("Give me a bottle of rum.")
import org.apache.commons.lang.StringUtils

class Parrot {
    static String speak(String text) {
        /Parrot says "$text"/

// Runtime mixin on String class. 
// mixin() is a GDK extension to Class.
String.mixin Parrot, StringUtils

assert 'Parrot says "mrhaki"' == 'mrhaki'.speak()
assert 'Groovy is so much...' == 'Groovy is so much fun.'.abbreviate(20)  // StringUtils mixin.


Goldfish said...

@Mixin isn't a compile-time modifier. Its also dynamic, meaning that any java code you write can NOT access the mixin nature. Believe me, I tried.

mrhaki said...

@Goldfish: thank you for your comment. I haven't tried it to call the class from Java code.

Tom said...

Does anyone know if this works for Grails GORM objects?

I've tried to add behavior to GORM domain objects and it doesn't seem to work.

HL said...

Nice trick, read most of your posts about Groovy, love it. Thanks for the good work.

Post a Comment