Pour le cas simple, il vaut mieux utiliser une carte.
Si vous voulez vraiment l'évaluer comme une fermeture (éventuellement pour créer votre propre DSL), vous devrez changer légèrement votre syntaxe comme John le fait remarquer. Voici une façon de le faire en utilisant une classe Builder pour évaluer la "quelque chose" fermeture dans tout ce qui est passé au constructeur.
Il utilise metaprogramming groovy pour intercepter des appels avec la méthode/propriété manquante et pour les sauver de:
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")
Merci beaucoup pour clarifier ce problème. Une carte est certainement utile et avec votre aide, je peux définir et accéder à un. J'ai été troublé par la définition d'une classe de domaine GORM, qui, je pense, utilise des fermetures. Si je voulais définir mes données dans un tel style, comment pourrais-je le lire? – Daniel
La classe de domaine GORM utilise des fermetures pour des choses telles que les contraintes et les mappages de bases de données, mais elle a implémenté un DSL pour exécuter et évaluer la fermeture. C'est beaucoup plus de travail que de simplement utiliser une carte, mais cela peut être utile si vous essayez de sécher le code et de donner à l'utilisateur la possibilité d'exprimer des choses dans un langage plus spécifique à la tâche que groovy normal. Pour ce que vous essayez de faire, John a raison, il suffit d'utiliser une carte. –
Wow, réponse fantastique, Ted. Je n'ai pas eu le temps de mettre dans l'exemple de code de métaprogrammation. :) –