Groovy Mixins?

Я пытаюсь добавить класс в свое приложение Groovy / Grails и использую синтаксис, определенный в документации, но продолжаю получать сообщение об ошибке.

У меня есть класс домена, который выглядит так:

class Person {
  mixin(ImagesMixin)

  // ...
}

Компилируется нормально, но по какой-то причине не работает. Файл, содержащий ImagesMixin, находится в моем каталоге /src/groovy/.

Я безуспешно пробовал использовать Groovy версий 1.5.7 и 1.6-RC1. Кто-нибудь знает, что я делаю не так?

трассировки стека:

2008-12-30 17:58:25.258::WARN:  Failed startup of context org.mortbay.jetty.webapp.WebAppContext@562791{/FinalTransmission,/home/kuccello/Development/workspaces/lifeforce/FinalTransmission/web-app}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError
    at java.security.AccessController.doPrivileged(Native Method)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
    at Init_groovy$_run_closure6.doCall(Init_groovy:131)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
    at gant.Gant.dispatch(Gant.groovy:271)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:436)
    at gant.Gant.processArgs(Gant.groovy:372)
Caused by: java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at Episode.class$(Episode.groovy)
    at Episode.<clinit>(Episode.groovy)
    ... 13 more
Caused by: groovy.lang.MissingMethodException: No signature of method: static Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
    at Broadcast.<clinit>(MyClass.groovy:17)
    ... 17 more
2008-12-30 17:58:25.259::WARN:  Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError:
groovy.lang.MissingMethodException: No signature of method: Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
    at Broadcast.<clinit>(Person.groovy:17)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at Episode.class$(BelongsToMyClass.groovy)
    at Episode.<clinit>(BelongsToMyClass.groovy)
    at java.security.AccessController.doPrivileged(Native Method)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
    at Init_groovy$_run_closure6.doCall(Init_groovy:131)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
    at gant.Gant.dispatch(Gant.groovy:271)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:436)
    at gant.Gant.processArgs(Gant.groovy:372)
2008-12-30 17:58:25.271::INFO:  Started [email protected]:8080

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

user339047 28.02.2012 02:41
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
1
9 853
7

Ответы 7

Я предполагаю, что то, что вы видели, скорее предложение, чем функция;) Groovy пока не поддерживает миксины из коробки таким образом (если вообще когда-либо). Но есть сторонняя библиотека, которую можно использовать для эмуляции такого поведения: Injecto. И миксины могут быть определены с помощью AST-Macros в версии Groovy 1.6 (которая еще не является окончательной).

Вы всегда должны проверять, читаете ли вы документацию из настоящего Groovy-проекта или из проекта GroovyJSR (который, скорее, является местом, где собираются предложения).

Другой способ - использовать старый добрый MOP для внедрения поведения в классные классы путем изменения метаклассов.

Ваше здоровье

К сведению: сейчас в Grails есть такое понятие, как «встроенные» домены, но с ним есть проблемы. Здесь вы можете логически включить один домен как часть другого, и все его поля будут физически присутствовать в одной таблице БД. Например, если вы обнаружите, что у вас есть одно и то же подмножество полей, появляющееся в нескольких таблицах, например, уличный адрес / город / штат / почтовый индекс, вы можете определить домен StreetAddress и встроить его. Одна из текущих проблем заключается в том, что Grails по-прежнему будет создавать таблицу street_address в дополнение к встраиванию ее полей в другие таблицы (если вы не играете в трюки). Похоже, для этого есть отправленные исправления.

Я не думаю, что вы используете правильный синтаксис миксина. Попробуй это:

class MyMixin {
    static doStuff(Person) {
        'stuff was done'
    }
}

class Person {}

Person.mixin MyMixin

new Person().doStuff()

должен ли doStuff() быть статичным?

Armand 29.03.2011 20:20

Это решение не работает: Person.doStuff () не работает, в чем весь смысл создания статического метода, чтобы использовать его в статическом контексте, верно? ; -) Статические миксины Groovy все еще не работают, начиная с 1.8, возможно, в 2.0 у нас будут рабочие статические миксины. До тех пор вам нужно перенести родительскую статику MOP в дочерний класс (классы), что далеко не идеально. Возьмите хорошее к плохому, в целом Groovy великолепен, и, я думаю, он находится на подъеме.

virtualeyes 26.04.2011 22:40

Начиная с Groovy 1.6, вы можете применить миксин во время компиляции к классу с помощью аннотации.

@Mixin(ImagesMixin)
class Person {
}

Или вы можете применить миксин во время выполнения следующим образом:

def myMixin = ImagesMixin
Person.mixin myMixin

Последний подход более динамичен, поскольку класс для микширования может быть определен во время выполнения. Дополнительная информация о миксинах Groovy доступна в здесь.

По моему опыту, многие методы метапрограммирования классов предметной области просто не работают. Я точно не знаю почему, но подозреваю, что это связано с тем, что эти классы уже очень сильно метапрограммированы средой выполнения Grails. В целом мой подход

  • Попробуйте метапрограммирование на POGO в консоли Groovy
  • Если это сработает, попробуйте его в некоммерческом классе в консоли Grails.
  • Если это сработает, попробуйте его в доменном классе в консоли Grails. Если это не работает, то это должно быть потому, что это класс предметной области (а не проблема с синтаксисом). На этом этапе рекомендуется попытаться найти другой способ достижения цели. Если это невозможно, используйте комбинацию списка рассылки Grails и / или Stackoverflow и / или исходного кода Grails, чтобы попытаться заставить метапрограммирование работать.

В случае, если это кому-то поможет, следуя приведенному выше комментарию @virtualeyes, я обнаружил, что

Person.doStuff()

завершится ошибкой, если вы сначала не вызовете следующее:

new Person().doStuff()
Person.doStuff()

после чего статический метод класса, похоже, работает (для меня, используя Grails 2.2.4), я думаю, это связано с инициализацией класса или чем-то еще, но я попробовал:

Person.metaClass.initialize()
Person.doStuff()

и это не сработало!

Объекты предметной области Grails уже сильно метапрограммированы. Вместо заводного миксина попробуйте:

@grails.util.Mixin(ImagesMixin)
    class Person {
}

Также важно отметить, что методы Gorm, которые добавляет grails, появляются после того, как методы добавлены через mixin, и вы не сможете вызывать их из смешанного метода, поэтому вам может потребоваться добавить объект домена в качестве аргумента к любому смешанному методу. методы, если вы собираетесь ссылаться на динамические средства поиска или сеанс гибернации или что-то еще.

Dave 12.09.2014 23:10

Используйте черты характера!

Черты - причина, по которой они удалили поддержку миксинов, потому что они просто лучше. Это в основном реализованные абстрактные классы. Позволяет использовать несколько классов и управлять ими как частичными классами.

trait A {
    void printSomething() {
        println "foobar"
    }
}

class B implements A {
    void printAnything() {
        printSomething()
    }
}

new B().printAnything() 

Попробуйте!

Другие вопросы по теме