2013-10-23 28 views
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)))) 
+0

是超类和子类记录还是Java类? – Jared314

+0

@ Jared314 Java类。我刚刚编辑了这个问题来反映这一点。谢谢 – tjb1982

回答

0

cast的问题是,它像一个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并且扩展该超级类型的协议。

0

编辑:从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] [])))) 

基于delegating-proxy一个稍微好一点的答案与

(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应该有一个等待强制对象的类型。在这种情况下,类型提示不起作用。

+0

谢谢。是的,这绝对是原来的问题。 – tjb1982