2015-09-02 4 views
4

Я работаю над модулем Java, который использует Groovy как зависимость времени компиляции, и я хотел бы добавить метод к моему классу Java Person (как Groovy JDK) без написания кода Groovy.Добавление методов в класс с использованием Groovy в Java

В Groovy я бы добиться этого, как этот

Person.meta.doSomething = { String param -> println "do something: ${param}" } 

Как я могу сделать это с помощью Groovy формы API Java?

EDIT 1:

я реализовал следующие до сих пор, и я почти там. Я создаю экземпляр класса Expando для Person и зарегистрирую MethodClosure, который делегирует вызов метода методу в классе PersonDefaultMethods.

ExpandoMetaClass expando = new ExpandoMetaClass (Person.class, true, false); 
expando.registerInstanceMethod ("format", new MethodClosure (new PersonDefaultMethods(), "format")); 
expando.initialize(); 

PersonDefaultMethods содержит реализацию методов я заявленных в классе Expando.

public class PersonDefaultMethods { 
    public String format(String format) { 
     return this.toString(); // this one gets called 
    } 

    public String format(Person self, String format) { // but I want this method to be called 
     return self.getFirstname() + " " + self.getLastname(); 
    } 
} 

Когда я знаю, что выполнить Groovy скрипт в этом контексте я в состоянии вызвать метод format на Person инстанции, но я не могу получить доступ к delegate, как я обычно можно с помощью замыкания.

EDIT 2:

Подход с использованием закрывающий подкласса или анонимный класс закрытия терпит неудачу в моей реализации.

ExpandoMetaClass expando = new ExpandoMetaClass(Person.class, true, false); 
expando.registerInstanceMethod("format", new Closure(this) { 

    @Override 
    public Object call(Object arguments) { 
     return super.call(arguments); 
    } 

    @Override 
    public Class[] getParameterTypes() { 
     return new Class[] { String.class}; 
    } 
    }); 
expando.initialize(); 

Это делает свою работу. Спасибо.

+0

Даже если вы можете заставить это работать, разве ваш код не станет бесполезным для поиска и вызовов реестра? Java не подходит для такого расширения экземпляра. Отсюда Groovy –

+0

Я абсолютно с тобой согласен. Единственная причина, по которой я пытаюсь использовать этот подход, заключается в том, что моя компания использует Eclipse (без поддержки Groovy), и если я начну класть классы Groovy в свое рабочее пространство, проект больше не будет построен ... Я знаю, что это плохо но я не могу его изменить (пока). – saw303

+1

re: «невозможно получить доступ к делегату».В MethodClosure делегат/владелец используется для вызова метода, здесь PersonDefaultMethods, поэтому он не будет работать так. Вам понадобится подкласс Closure. – blackdrag

ответ

2

Вы можете получить текущий мета-класс через GroovySystem.getMetaClassRegistry().getMetaClass(Person.class);. Но для имитации выше вы должны сделать несколько вещей вручную Groovy делает для вас в фоновом режиме.

  • Прежде всего, вам понадобится ExpandoMetaClass (короткая ЭМС). Если метакласс сверху не является EMC, вам необходимо создать его и зарегистрировать в реестре: ExpandoMetaClass emc = new ExpandoMetaClass(Person.class).
  • Далее вам нужно будет позвонить registerInstanceMethod с помощью String и Closure или MetaMethod. Вариант выше - это версия Closure и будет вызывать другую в фоновом режиме.
  • Чтобы следовать соглашениям Groovy, вам необходимо создать подкласс Closure (возможно, анонимный) с помощью метода doCall подписи, в которой вы хотите, чтобы ваш метод был. Строка для registerInstanceMethod будет именем метода
  • Вы также можете использовать один из существующих подклассов MetaMethod (или свой собственный), чтобы попасть туда.
+0

Спасибо за ваше объяснение. Я применил его, но теперь я столкнулся с исключением (см. Обновленный вопрос) – saw303

 Смежные вопросы

  • Нет связанных вопросов^_^