Groovy динамическое свойство на объект - PullRequest
5 голосов
/ 04 июля 2011

Использование Groovy 1.8. Я пытаюсь создать динамическое определение класса, которое будет кэшировать свойства для каждого объекта. Я использовал propertyMissing без добавления свойства объекта. Я просто думаю, что кэширование свойств будет более эффективным. Правильно?

Обратите внимание, что каждый экземпляр должен иметь свои собственные различные свойства.

Код ниже работает нормально:

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

def x = new C()
x.prop

выведет:

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

Если мне нужно это проблематично:

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

Для A я дошел до "создать новое свойство", но строка this.metaClass."$name" = "Dyna prop $name" не удалась с: No such property: p1 for class at line 5

Что не так?

Ответы [ 3 ]

8 голосов
/ 04 июля 2011

Этот код должен делать то, что вы хотите:

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

Это выводит:

create new propery p1
created new propery p1
Dyna prop p1
Dyna prop p1
6 голосов
/ 28 июля 2011

Почему бы вам не сохранить ваши динамические свойства в простой 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"

Это стандартный пример: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

Обратите внимание, вам не нужно проверять, действительно ли свойство отсутствует ... если оно не будет отсутствовать, метод не будет вызван в первую очередь.

1 голос
/ 04 июля 2011

ExpandoMetaClass на самом деле не предназначен для использования после инициализации или переменных экземпляра (см. Ссылку ниже, по крайней мере, для версии 1.6 или старше).

Может быть, вы хотите использовать Mixins времени выполнения . Больше информации здесь и здесь .

Возможно, вы захотите прочитать blogpost , который предоставляет обходной путь для определения свойств во время выполнения. И связанный с ним groovy bug (это не совсем ошибка), связанный с ним.

Я видел в разделе комментариев и проверял, по крайней мере, в версии 1.6 Документация ExpandoMetaClass:

По умолчанию методы разрешены только быть добавлен до инициализации () называется. Другими словами, вы создаете новый ExpandoMetaClass, добавить несколько методов и затем вызовите initialize (). если ты попытаться добавить новые методы после initialize () был назван ошибкой будет брошен.

...