Замкнутая мультиметодная проблема диспата - PullRequest
4 голосов
/ 20 ноября 2010

У меня есть два источника:

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

и

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

, и я уверен, что (isa? odo.Complex.State odo.IComplex.PolarComplex) равно true

, но когда явыполнить

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

Я получу

java.lang.IllegalArgumentException: нет метода в мультиметоде 'polar-complex' для значения отправки: класс odo.Complex.State

Можете ли вы сказать мне, почему?

1 Ответ

1 голос
/ 21 ноября 2010

Я обнаружил, что в контексте своего определения var PolarComplex связан с картой, содержащей информацию о протоколе, а не с классом.Поэтому правильная реализация мультиметода будет

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

или

(defmethod polar-complex odo.IComplex.PolarComplex [num abs arg]
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...