Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: moved text out of code block

...

Code Block
class Person {
   String name = "Fred"
}

def methodName = "Bob"

Person.metaClass."changeNameTo${methodName}" = {-> delegate.name = "Bob" }


def p = new Person()

assert "Fred" == p.name

p.changeNameToBob()

assert "Bob" == p.name

The

...

same

...

concept

...

can

...

be

...

applied

...

to

...

static

...

methods

...

and

...

properties.

...

A more elaborate example

In Grails we have a concept of dynamic codecs, classes that can encode and decode data.

...

Code Block
import org.springframework.web.util.HtmlUtils
class HTMLCodec {
    static encode = { theTarget ->
        HtmlUtils.htmlEscape(theTarget.toString())
    }

        static decode = { theTarget ->
    	HtmlUtils.htmlUnescape(theTarget.toString())
    }
}

So what we do with these classes is to evaluate the convention and add "encodeAsXXX" methods to every object based on the first part of the name of the codec class such as "encodeAsHTML". The pseudo code to achieve this is below:

Code Block
def codecs = classes.findAll { it.name.endsWith('Codec') }

codecs.each { codec ->
    
    Object.metaClass."encodeAs${codec.name-'Codec'}" = { codec.newInstance().encode(delegate) }
    Object.metaClass."decodeFrom${codec.name-'Codec'}" = { codec.newInstance().decode(delegate) }
}


def html = '<html><body>hello</body></html>'

assert '&lt;html&gt;&lt;body&gt;hello&lt;/body&gt;&lt;/html&gt;' == html.encodeAsHTML()

...