2011-10-13 4 views
22

Les réponses de this question about the Groovy way to dynamically invoke a static method étaient très serviables mais je ne parviens pas le cas suivant:manière Groovy dynamiquement instancier une classe de chaîne

Je définis une simple classe Groovy:

class Item { 
    def id = 1 
    def data = [ "a", "b" ] 
} 

Je puis définir une classe simple utilitaire qui veut charger dynamiquement la classe de l'objet:

class Util { 
    static def main(args) { 
    def cls = "Item" as Class 
    def instance = cls.newInstance() 
    println instance.toString() 
    } 
} 

Util.groovy se trouve dans le même dossier que Item.groovy

Lorsque je tente de lancer Util.groovy je reçois l'erreur suivante:

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: 
Cannot cast object 'Item' with class 'java.lang.String' 
to class 'java.lang.Class' due to: 
java.lang.ClassNotFoundException: Item 
     at Util.main(Util.groovy:3) 

La seule façon que je pouvais le faire fonctionner à l'aide était groovyc à précompiler Item.groovy, mais cela manque le point d'être Groovy :)

Répondre

28

cela fonctionne, en utilisant le underlying GroovyClassLoader:

def instance = this.class.classLoader.loadClass('Item', true, false)?.newInstance() 
+1

Vous devriez probablement remplacer 'this.class' par' this.getClass() '. Il est généralement recommandé d'utiliser la méthode complète pour éviter les [recherches de propriétés ou de cartes (ou les substitutions invokeMethod)] (http://groovy.329449.n5.nabble.com/class-vs-getClass-td368617.html). – OverZealous

+8

Pourquoi s'embêter quand on sait que ce n'est pas une carte? Embrassez la dynamique! ;-) –

+0

Ça a marché! Merci Tim! :) –

5

Je viens de le faire et a trouvé une façon intéressante - donc je pensais que je reviendrais et mentionner.

J'ai eu un problème avec cela parce que je voulais passer une valeur à newInstance (utiliser un constructeur non défini par défaut) et toutes les solutions qui semblait être un peu de travail (je suis paresseux, d'accord?)

Quoi qu'il en soit

, supposons que vous voulez créer un nouveau entier (5) ... essayez ceci:

a vraiment bien
c = "java.lang.Integer" 
p = "5" 
def result = Eval.me("return new ${c}(${p})") 
assert(result == 5) 

bien que je suis sûr qu'il est de la plus lente solution possible. A l'avantage que la méthode est applicable à beaucoup d'autres situations.

+3

IT SEEMS javascript plagia :) –

+0

@Bill Intéressant au niveau intellectuel, mais ce n'est vraiment pas de manière groovy, comme Abdennour TOUMI dit –

+0

Je suis d'accord, je viens de le mentionner pour la complétude et la facilité - parfois vous écrivez juste un - hors script et c'est facile à retenir et flexible. –

Questions connexes