Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a Groovy class looks as Map to Java code without implementing Map interface explicitly

I want to implement a custom Map-like class where most of the functionality is delegated to a nested Map delegate instance. And, I want this class to look like a Map to a "true" Java classes. Therefore I tried to do the following:

class ConfigurationMap implements Map {
    def inner = [:]

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

    // my methods here
    ...

And of course, this doesn't work :-( Groovy demands the class to implement Map interface methods, despite at runtime they would be handled by missedMissing(). If I remove the implements clause:

class ConfigurationMap {
    def inner = [:]

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

it works for Groovy (i.e. the instance truly behaves like a Map), but I cannot use it as a Map from Java code:

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

And advice to my on how can I keep my class short (i.e. do not implement Map explicitly) and still make the class look as Map to Java?

like image 918
Vladimir Dyuzhev Avatar asked Jan 20 '23 19:01

Vladimir Dyuzhev


1 Answers

I think if you use the @Delegate annotation, that the compiled bytecode will work properly from 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()
like image 134
Ted Naleid Avatar answered May 11 '23 10:05

Ted Naleid