2017-08-21 4 views
2

J'essaie de trouver un moyen de .invoke() méthodes d'un seul argument, sans connaître le type de l'argument à l'exécution. Par exemple, en passant un nom de propriété à la fonction suivante, je voudrais définir la valeur de la propriété. Pour l'instant, il est codé en dur comme Double/TYPE, mais vraiment la fonction devrait être autorisée à prendre n'importe quel type de value arg. Les noms de propriété, et donc le type d'argument value, ne sont pas connus avant l'exécution, mais il semble que la méthode nécessite un tableau de primitives, au moins pour les types de nombre.Clojure: Appeler .invoke sans connaître les types d'arg au moment de la compilation

(defn set-prop-val! 
    "Sets property value to value. Uses reflection." 
    [obj prop value] 
    (let [methodname (str "set" prop)] 
    (.. obj 
     getClass 
     (getMethod methodname (into-array [Double/TYPE])) 
     (invoke obj (into-array [value]))))) 

(set-prop-val! (Button.) "TranslateX" 13.99) 

Dans la fonction ci-dessus, en essayant à la place (getMethod methodname (into-array [(class value)])) ne fonctionne pas, et je reçois NoSuchMethodException javafx.scene.control.Button.setTranslateX(java.lang.Double) parce qu'il veut un double pas Double.

Ce que je voudrais faire est pour les nombres pour obtenir le type primitif lors de l'exécution, mais toutes les tentatives d'appeler une méthode statique d'une instance ont échoué, par exemple (. (class 19.5) TYPE) (dans ce cas, je reçois IllegalArgumentException No matching field found: TYPE for class java.lang.Class)

Il semble que seulement Double/TYPE fonctionne, même si (= (class 19.5) Double) renvoie true.

Alors quelques questions viennent de ceci:

  1. Comment appeler une méthode statique, comme TYPE d'une instance?
  2. Y at-il une utilisation pour double-array ici? Cela m'obtient le tableau pour porter les valeurs pour le .invoke, qui ne semble même pas nécessaire de toute façon, mais pas le tableau Class[double] nécessaire pour .getMethod. Dois-je utiliser clojure.reflect à la place?

Répondre

1

J'ai trouvé que je pouvais simplement utiliser clojure.lang.Reflector/invokeInstanceMethod pour faire exactement ce dont j'avais besoin.