2017-08-21 1 views
2

Ich versuche, einen Weg zu .invoke() Methoden eines einzigen arg, ohne zu wissen, die Art der arg zur Laufzeit.Clojure: Aufruf .invoke ohne zu wissen, arg Typen zum Zeitpunkt der Kompilierung

Wenn Sie beispielsweise einen Eigenschaftsnamen an die folgende Funktion übergeben, möchte ich den Wert der Eigenschaft festlegen. Für jetzt ist es fest codiert als Double/TYPE, aber wirklich sollte die Funktion erlaubt sein, irgendeine Art von value Arg zu nehmen.

Die Eigenschaftsnamen und daher der Typ von arg value ist bis zur Laufzeit nicht bekannt, es scheint jedoch, dass die Methode ein Array von Primitiven erfordert, zumindest für Zahlentypen.

(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) 

In der obigen Funktion und versucht stattdessen (getMethod methodname (into-array [(class value)])) nicht funktioniert, und ich bekomme NoSuchMethodException javafx.scene.control.Button.setTranslateX(java.lang.Double), weil es ein double kein Double will.

Was ich möchte, ist für Zahlen tun, um den primitiven Typen zur Laufzeit zu bekommen, aber alle Versuche, eine statische Methode von einer Instanz versagt haben Aufruf, zB (. (class 19.5) TYPE) (in diesem Fall ich IllegalArgumentException No matching field found: TYPE for class java.lang.Class)

Es scheint nur Double/TYPE funktioniert, obwohl (= (class 19.5) Double)true zurückgibt.

So ein paar Fragen kommen aus diesem:

  1. Wie rufe ich eine statische Methode, wie TYPE von einer Instanz?
  2. Gibt es eine Verwendung für double-array hier? Das bringt mir das Array, um die Werte für die .invoke zu tragen, die sowieso nicht notwendig erscheint, aber nicht die Class[double] Array benötigt für .getMethod.
  3. Soll ich stattdessen clojure.reflect verwenden?

Antwort

1

Ich fand, ich könnte einfach clojure.lang.Reflector/invokeInstanceMethod verwenden, genau das zu tun, was ich brauche.

Verwandte Themen