2010-01-24 7 views
3

je voudrais stocker quelques propriétés dans une fermeture statique et d'y accéder plus tard au cours d'un appel de méthode:valeurs d'accès de fermeture statique dans Groovy

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

Alors, comment puis-je écrire une méthode au sein de la personne, qui récupère cette donnée stockée?

Répondre

6

Si elles doivent être initialisées par une fermeture, au lieu d'une carte, alors quelqu'un doit exécuter la fermeture afin de ramasser et d'enregistrer les valeurs telles qu'elles sont définies.

Votre syntaxe n'est pas valide. Rappelez-vous que les fermetures ne sont que des méthodes anonymes. Votre syntaxe ressemble à la définition d'une carte, mais les fermetures doivent appeler des méthodes, définir des variables ou renvoyer des cartes. par exemple.

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 

Alors bien sûr, celui qui exécute la fermeture doit avoir la métaprogrammation appropriée pour enregistrer les résultats.

Il semble que ce que vous voulez vraiment, c'est simplement de définir une carte.

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

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

+0

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. –

+0

Wow, réponse fantastique, Ted. Je n'ai pas eu le temps de mettre dans l'exemple de code de métaprogrammation. :) –

7

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") 
+0

J'ai aussi lancé un post sur mon blog avec une solution un peu plus générique: http://naleid.com/blog/2010/01/24/interrogating-arbitrary-groovy-closures-for-values/ –

0

C'est ce que je suis venu avec pour extraire les propriétés de fermeture statiques:

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 
Questions connexes