代码之家  ›  专栏  ›  技术社区  ›  Odomontois

Clojure多方法dispath问题

  •  4
  • Odomontois  · 技术社区  · 13 年前

    我有两个消息来源:

    (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:否 多方法“极性复合物”中的方法 发送值:类 复杂状态

    你能告诉我为什么吗?

    1 回复  |  直到 13 年前
        1
  •  1
  •   Odomontois    13 年前

    我发现在它的定义中 PolarComplex 绑定到包含协议信息的映射,而不是绑定到类。所以正确实现multimethod将是

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