Agregar dinámicamente una propiedad o método a un objeto en groovy


¿Es posible agregar una propiedad o un método a un objeto dinámicamente en Groovy? Esto es lo que he intentado hasta ahora:

class Greet {
  def name
  Greet(who) { name = who[0].toUpperCase() + [1..-1] }
  def salute() { println "Hello $name!" }
}

g = new Greet('world')  // create object
g.salute()              // Output "Hello World!"

g.bye = { println "Goodbye, $name" }
g.bye()

Pero obtengo la siguiente excepción:

Hello World!
Caught: groovy.lang.MissingPropertyException: No such property: bye for class: Greet
Possible solutions: name
    at test.run(greet.groovy:11)
Author: Alex Spurling, 2011-01-24

1 answers

Si solo desea agregar el método bye() a la instancia única g de la clase Greet, debe hacer:

g.metaClass.bye = { println "Goodbye, $name" }
g.bye()

De lo contrario, para agregar bye() a todas las instancias de Greet (de ahora en adelante), llame a

Greet.metaClass.bye = { println "Goodbye, $name" }

Pero tendría que hacer esto antes de crear una instancia de la clase Greet

Aquí hay una página sobre la metaClase por instancia

Y aquí está la página sobre metaclases en general


También, hay un error en su constructor. Te falta who desde delante de tu [1..-1] y si al constructor se le pasa un String de menos de 2 caracteres de longitud, lanzará una excepción

Una versión mejor podría ser:

Greet( String who ) { 
  name = who.inject( '' ) { String s, String c ->
    s += s ? c.toLowerCase() : c.toUpperCase()
  }
}

Como se menciona en los comentarios,

Greet( String who ) { 
  name = who.capitalize()
}

Es el camino correcto

 57
Author: tim_yates,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-30 10:59:57