Область применения Groovy ExpandoMetaClass?
Groovy выставляет ExpandoMetaClass
это позволяет вам динамически добавлять методы / свойства экземпляра и класса в POJO. Я хотел бы использовать его для добавления метода экземпляра к одному из моих классов Java:
public class Fizz {
// ...etc.
}
Fizz fizz = new Fizz();
fizz.metaClass.doStuff = { String blah -> fizz.buzz(blah) }
Это будет эквивалентно рефакторингу Fizz
класс иметь:
public class Fizz {
// ctors, getters/setters, etc...
public void doStuff(String blah) {
buzz(blah);
}
}
Мой вопрос:
Это добавляет doStuff(String blah)
только этот конкретный случай Fizz
? Или сделать все случаи Fizz
теперь есть doStuff(String blah)
метод экземпляра?
Если первое, как я могу получить все экземпляры Fizz
иметь doStuff
метод экземпляра? Я знаю, что если я сделал Groovy:
fizz.metaClass.doStuff << { String blah -> fizz.buzz(blah) }
Тогда это добавило бы метод статического класса в Fizz
, такие как Fizz.doStuff(String blah)
, но это не то, что я хочу. Я просто хочу, чтобы все случаи Fizz
чтобы теперь иметь экземпляр метода с именем doStuff
, Идеи?
1 ответ
Во-первых, когда вы добавляете в основной класс Fizz, его экземпляры не получают метод, так как экземпляры уже разложены и добавлены в память.
Таким образом, один из способов достижения этого заключается в использовании сигнатуры метода из исходного класса. Поэтому вместо
fizz.doStuff(blah)
вызовите метод класса. Следовательно
fizz.&doStuff(blah)
Это получает сигнатуру метода от исходного класса, но использует атрибуты из экземпляра. Однако, как вы можете себе представить, поскольку он вызывает исходный класс, это немного тяжелый вызов.
Теперь одна альтернатива для каждого экземпляра состоит в том, чтобы сделать экземпляры ExpandoMetaClass экземплярами Fizz. Следовательно...
Fizz.metaClass.doStuff = {return "blah"}
fizz = new Fizz()
Fizz.metaClass.doOtherStuff = {return "more blah"}
assert fizz.doOtherStuff() == "more blah"
Надеюсь это поможет
ОБНОВИТЬ:
Пример полного кода:
class Fizz{
}
Fizz.metaClass.doOtherStuff = {return "more blah"}
def fizz = new Fizz()
assert fizz.doOtherStuff() == "more blah"
def fizz1 = new Fizz()
assert fizz1.doOtherStuff() == "more blah"