Pergunta

Eu tenho essas duas fontes:

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

e

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

E eu tenho garantido que (isa? odo.Complex.State odo.IComplex.PolarComplex) é true

Mas quando eu executo

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

eu recebo

java.lang.illegalargumentException: nenhum método no multimethod 'polar-complexo' para o valor de despacho: classe odo.complex.state

Pode me dizer por quê?

Foi útil?

Solução

Eu descobri isso no contexto de sua definição var PolarComplex é obrigado ao mapa contendo informações sobre o protocolo, não para a classe. Portanto, a implementação correta do Multimethod será

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

ou

(defmethod polar-complex odo.IComplex.PolarComplex [num abs arg]
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top