1

例如,

(defprotocol P
  (foo [x])
  (bar [x]))


(extend-protocol P

  Superclass ;; a java abstract class
  (foo [x]
    (println "superclass"))

  Subclass ;; a concrete java class implementing the above abstract class
  (foo [x]
    (foo (cast Superclass x))))

如果打电话

(foo subclass-instance)

我显然会得到堆栈溢出,但是有什么方法可以完成我在这里尝试做的事情,即调用相同的函数但伪装成通用超类/接口?

更新:一个更清晰的示例演示了我所要求的用例:

(defprotocol P
  (extract-properties-into-map [self]))

(extend-protocol P
  PropertyContainer  ;; abstract class
  (extract-properties-into-map
    [this]
    (into {} (for [[k v] (.getProperties this)] [(keyword k) (read-string v)])))

  Foo
  (extract-properties-into-map
    [this]
    (assoc {:properties (extract-properties-into-map
                          ^PropertyContainer this)} ;; this is where it falls apart
      :foo-type (.getFooType this)
      :foo-permissions (.getPermissions this)
      :foo-whatever (.getWhatever this))))
4

2 回答 2

0

问题cast在于它像 a 一样工作type assertion,如果您的对象不满足 is-a 关系,则只会抛出异常。

(defn cast
  "Throws a ClassCastException if x is not a c, else returns x."
  {:added "1.0"
   :static true}
  [^Class c x] 
  (. c (cast x)))

没有新的接口被返回到不同的函数中调度,即你有一个堆栈溢出。

我不确定为 ? 扩展协议意味着什么Interface?由于您提供了一个实现,我想您应该首先定义一个type并在该超类型上扩展协议。

于 2013-10-23T15:58:33.240 回答
0

delegating-proxy编辑:基于https://gist.github.com/michalmarczyk/1715851的更好的答案

(defprotocol P
   (foo [x])
   (bar [x]))


(extend-protocol P

  Number ;; a java abstract class
  (foo [x]
      (println "superclass:" x))

  Integer ;; a concrete java class implementing the above abstract class
   (foo [x]
    (foo (delegating-proxy x [Number] []))))

调用

(foo (Integer. 1))
=> superclass: 1

虽然它按照问题要求进行,但它现在包装了原始x. 根据要求,委托foo给协议中未包含的功能可能会更好,也许superfoo

(defn superfoo [x] { :byte (.byteValue x) })

(defprotocol P
  (foo [x])
  (bar [x]))


(extend-protocol P

  Number ;; a java abstract class
   (foo [x]
     (superfoo x))

  Integer ;; a concrete java class implementing the above abstract class
    (foo [x]
      (merge (superfoo x) { :f (.floatValue x)})))

我认为根本问题是协议不知道类继承。此外,似乎 Clojure 应该等待将对象强制转换为类型。在这种情况下,类型提示不起作用。

于 2013-10-23T18:28:33.773 回答