2011-07-04 14 views
5

Uso de Groovy 1.8. Intento crear una definición de clase dinámica que almacene las propiedades por objeto. Utilicé propertyMissing sin agregar la propiedad al objeto muy bien. Solo creo que el almacenamiento en caché de las propiedades sería más eficiente. ¿Derecha?Propiedad dinámica Groovy por objeto

Tenga en cuenta que cada instancia debe tener sus propias propiedades diferentes.

El código siguiente funciona bien:

class C {} 
def c = new C() 
c.metaClass.prop = "a C property" 
println c.prop 

def x = new C() 
x.prop 

la Salida:

a C property 
groovy.lang.MissingPropertyException: No such property: prop for class: C 

Si necesito a esta problemática:

class A { 
    def propertyMissing(String name) { 
     if(!this.hasProperty(name)) { 
      println "create new propery $name" 
      this.metaClass."$name" = "Dyna prop $name" 
      println "created new propery $name" 
     } 
     this.metaClass."$name" 
    } 
} 

a = new A() 
println a.p1 

Para A, que llegar lo más lejos " crear nueva propiedad ", pero la línea this.metaClass."$name" = "Dyna prop $name" falla con: No such property: p1 for class at line 5

¿Cuál es el problema?

Respuesta

8

Este código debe hacer lo que quiera:

class A { 
    A() { 
    def mc = new ExpandoMetaClass(A, false, true) 
    mc.initialize() 
    this.metaClass = mc 
    } 

    def propertyMissing(String name) { 
    println "create new propery $name" 
    def result = "Dyna prop $name" 
    this.metaClass."$name" = result 
    println "created new propery $name" 
    result 
    } 
} 

a = new A() 
println a.p1 
println a.p1 

que da salida:

create new propery p1 
created new propery p1 
Dyna prop p1 
Dyna prop p1 
1

ExpandoMetaClass en realidad no está diseñado para ser utilizado después de las variables de inicialización o de instancia (ver la referencia más abajo al menos para 1.6 o más).

Quizás desee utilizar Runtime mixins. Más información here y here.

Es posible que desee leer un blogpost, que se proporciona una solución para definir las propiedades en tiempo de ejecución. Y el relacionado groovy bug (que no es realmente un error) relacionado con él.

que vi en la sección de comentarios y verifiqué al menos en la versión 1.6 ExpandoMetaClass documentación:

Por métodos predeterminados sólo se permiten a ser añadido antes de inicializar() es llamado . En otras palabras, crea un nuevo ExpandoMetaClass, agrega algunos métodos y luego llama a initialize(). Si intenta agregar nuevos métodos después de que se ha llamado initialize() se generará un error .

+0

Aha .. Solo puedes hacer eso en tiempo de compilación ... muy mal. – Ayman

+0

Puede usar Runtime mixin para el tiempo de ejecución – Manny

+0

Reparar el enlace roto de "blogpost": http: // blog.enfranchisedmind.com/2008/06/groovy-metaclass-bug/ –

6

¿Por qué no almacenar sus propiedades dinámicas de una manera sencilla HashMap?

class Foo { 
    def storage = [:] 
    def propertyMissing(String name, value) { storage[name] = value } 
    def propertyMissing(String name) { storage[name] } 
} 
def f = new Foo() 
f.foo = "bar" 

Este es el ejemplo típico de: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

Nota, que no tiene que comprobar si la propiedad es realmente falta ... si no se encuentra, el método no sería llamado en primer lugar.

Cuestiones relacionadas