开发者

Access values of static closure in Groovy

I'd like to store some properties in a static closure and later access them during a method call:

class Person {  
static someMap = { key1: "value1", key2: "value2" }  
}

So how can I write a m开发者_运维技巧ethod within Person, which retrieves this stored data?


For the simple case, you're better off using a map.

If you really do want to evaluate it as a closure (possibly to create your own DSL), you'll need to change your syntax slightly as John points out. Here's one way to do it using a Builder class to evaluate the "something" closure within whatever is passed to the builder.

It uses groovy metaprogramming to intercept calls with method/property missing and to save them off:

class SomethingBuilder {
    Map valueMap = [:]

    SomethingBuilder(object) {
        def callable = object.something
        callable.delegate = this
        callable.resolveStrategy = Closure.DELEGATE_FIRST
        callable()
    }

    def propertyMissing(String name) {
        return valueMap[name]
    }

    def propertyMissing(String name, value) {
        valueMap[name] = value
    }

    def methodMissing(String name, args) {
        if (args.size() == 1) {
            valueMap[name] = args[0]
        } else {
            valueMap[name] = args
        }
    }
}

class Person {
    static something = {
        key1 "value1"              // calls methodMissing("key1", ["value1"])
        key2("value2")             // calls methodMissing("key2", ["value2"])
        key3 = "value3"            // calls propertyMissing("key3", "value3")
        key4 "foo", "bar", "baz"   // calls methodMissing("key4", ["foo","bar","baz"])
    }
}

def builder = new SomethingBuilder(new Person())

assert "value1" == builder."key1"  // calls propertyMissing("key1")
assert "value2" == builder."key2"  // calls propertyMissing("key2")
assert "value3" == builder."key3"  // calls propertyMissing("key3")
assert ["foo", "bar", "baz"] == builder."key4"  // calls propertyMissing("key4")


If they need to be initialized by a closure, instead of a map, then somebody's got to run the closure in order to pick up and record the values as they're set.

Your syntax there isn't valid. Remember closures are just anonymous methods. Your syntax looks like you're trying to define a map, but closures would need to call methods, set variables or return maps. e.g.

static someClosure = { key1 = "value1"; key2 = "value2" } // set variables
static someClosure = { key1 "value1"; key2 = "value2" } // call methods
static someClosure = { [key1: "value1", key2: "value2"] } // return a map

Then of course whoever's running the closure needs to have the right metaprogramming to record the results.

It sounds like what you really want is just to define a map.

static someMap = [key1: "value1", key2: "value2"]


This is what I came up with to extract static closure properties:

class ClosureProps {

       Map props = [:]  
       ClosureProps(Closure c) {  
           c.delegate = this  
           c.each{"$it"()}  
       }  
       def methodMissing(String name, args) {  
           props[name] = args.collect{it}  
       }  
       def propertyMissing(String name) {  
           name  
       }  
}  

// Example  
class Team {

        static schema = {  
            table team  
            id teamID  
            roster column:playerID, cascade:[update,delete]  
        }  
}  
def c = new ClosureProps(Team.schema)  
println c.props.table  
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜