2010-11-20 8 views
3

Ich habe diese beiden Quellen:Clojure Multimethod- dispath Problem

(ns odo.IComplex) 
(gen-interface 
    :name odo.IComplex 
    :methods [ 
     [getReal [] Double] 
     [getImag [] Double] 
     [getAbs [] Double] 
     [getArg [] Double] 

     [setReal [Double] void] 
     [setImag [Double] void] 
     [setAbs [Double] void] 
     [setArg [Double] void]]) 

(defprotocol PolarComplex 
    (abs [this] [this value]) 
    (arg [this] [this value])) 

(defmulti polar-complex (fn([record abs arg] (class record)))) 

und

(ns odo.Complex 
    (:gen-class 
    :init init 
    :state state 
    :implements [odo.IComplex]) 
    (:use odo.IComplex)) 

(defrecord State [^Double imag ^Double real] 
    Object (toString [self] 
      (str real (if (>= imag 0) " + " " - ") (Math/abs imag) "j" 
      " : " (abs self) " * exp[ " (arg self) " ]")) 

    PolarComplex (abs [self]  (Math/sqrt (+ (* real real) (* imag imag)))) 
       (abs [self value] (polar-complex self value (arg self))) 

       (arg [self]  (Math/atan2 real imag)) 
       (arg [self value] (polar-complex self (abs self) value))) 

(defmethod polar-complex PolarComplex [num abs arg] 
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg)))) 

(defn -init [] [[] (atom (State. 0. 0.))]) 
(defn -getImag [self] (:imag @(.state self))) 
(defn -getReal [self] (:real @(.state self))) 
(defn -getAbs [self] (abs @(.state self))) 
(defn -getArg [self] (arg @(.state self))) 

(defn -setImag [self value] (swap! (.state self) assoc :imag value)) 
(defn -setReal [self value] (swap! (.state self) assoc :real value)) 
(defn -setAbs [self value] (swap! (.state self) abs value)) 
(defn -setArg [self value] (swap! (.state self) arg value)) 

(defn -toString [self] (str @(.state self))) 

und ich bin sicher, dass (isa? odo.Complex.State odo.IComplex.PolarComplex) ist true

aber wenn ich ausführen

(doto (odo.Complex.) 
    (.setArg (/ Math/PI 4.)) (.setAbs (Math/sqrt 2)) (println)) 

ich

java.lang.IllegalArgumentException: Keine Methode in Multimethod- 'polar-Komplex' Versandwert: Klasse odo.Complex.State

Können Sie mir sagen, warum?

+0

sein Ich weiß, dass diese Implementierung der Methode ungenau ist, weil PolarComplex Protokoll nicht Karte-ähnlichen Zugriff auf reale und komplexe Teile Garantierter ist. Aber das ist nur eine Frage des Verzichts. – Odomontois

Antwort

1

Ich habe entdeckt, dass im Zusammenhang mit seiner Definition var PolarComplex gebunden ist, um Informationen zu Protokoll, nicht zur Klasse zu enthalten. So korrekte Umsetzung der Multimethode wird

(defmethod polar-complex (:on-interface PolarComplex) [num abs arg] 
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg)))) 

oder

(defmethod polar-complex odo.IComplex.PolarComplex [num abs arg] 
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))