Как заставить класс Groovy выглядеть как код Map to Java без явной реализации интерфейса Map

Я хочу реализовать пользовательский класс, подобный Map, в котором большая часть функциональности делегирована вложенному экземпляру делегата Map. И я хочу, чтобы этот класс выглядел как карта "истинных" Java-классов. Поэтому я попытался сделать следующее:

class ConfigurationMap implements Map {
    def inner = [:]

    def methodMissing(String methodName,methodArgs) {
        return inner.invokeMethod(methodName,methodArgs)
    }

    // my methods here
    ...

И, конечно, это не работает:-( Groovy требует, чтобы класс реализовал методы интерфейса Map, несмотря на то, что во время выполнения они будут обрабатываться missedMissing(). Если я удалю implements пункт:

class ConfigurationMap {
    def inner = [:]

    def methodMissing(String methodName,methodArgs) {
        return inner.invokeMethod(methodName,methodArgs)
    }

это работает для Groovy (то есть экземпляр действительно ведет себя как карта), но я не могу использовать его как карту из кода Java:

ConfigurationMap cm = ConfigParser.parseConfig("foo.cfg");
assertEquals(0,cm.size()); // size() method is not defined :-(

И мой совет относительно того, как я могу сделать свой класс коротким (то есть не реализовывать Map явно) и при этом заставить класс выглядеть как Map to Java?

1 ответ

Решение

Я думаю, что если вы используете @Delegate примечание, что скомпилированный байт-код будет работать должным образом из Java.

class ConfigurationMap implements Map {
    @Delegate Map inner = [:]

    def myMethod() {
        return true
    }
}

ConfigurationMap cm = new ConfigurationMap()
cm.foo = "bar"
assert "bar" == cm.foo
assert true == cm.myMethod()
Другие вопросы по тегам