2015-08-23 20 views
5

我正试图扩展库DomKM/silk如何重用Clojure/Clojurescript中的deftype方法?

具体有deftype Route它实现协议Pattern,其中有方法的实现,我想在我的Pattern协议的自定义实现重用哪些。

https://github.com/DomKM/silk/blob/master/src/domkm/silk.cljx#L355

(deftype Route [name pattern] 
    Pattern 
    (-match [this -url] 
      (when-let [params (match pattern (url -url))] 
      (assoc params ::name name ::pattern pattern))) 
    (-unmatch [this params] 
      (->> (dissoc params ::name ::pattern) 
       (unmatch pattern) 
       url)) 
    (-match-validator [_] 
        map?) 
    (-unmatch-validators [_] 
         {})) 

好了,所以我的实现看起来在某种程度上是这样,但我想,以“继承” Route的方法。我的意思是先执行一些自定义逻辑,然后将其传递给原始Route方法。

(deftype MyRoute [name pattern] 
    silk/Pattern 
    (-match [this -url] 
    true) ;match logic here 
    (-unmatch [this {nm ::name :as params}] 
    true) ;unmatch logic here 
    (-match-validator [_] map?) 
    (-unmatch-validators [_] {})) 

这是怎么做的clojure/clojurescript?

+1

Clojure的设计师不喜欢方法的继承。我认为你不能以非常自然的方式做到这一点。你显然可以创建一个'Route'对象,并让'MyRoute'的方法委托给'Route'。 'deftype'创建的对象是Java类,所以你可以通过使用允许继承的两个Java互操作宏之一来执行你想要的操作:'proxy'和'gen-class'。 'gen-class'可能是矫枉过正的,所以如果你走这条路,我建议'proxy'。但是,这违背了Clojure的设计目标,因此您可能只需重新实现所需的代码。 – Mars

+0

'Route'中的函数并不大。如果你想做很多事情,你可以在'deftype'对象之外编写函数,并使用'Pattern'方法调用它们。 – Mars

+0

@Mars感谢您的回答!当我尝试使用代理:'(代理[路由] [名称模式]( - 匹配[]))'我得到一个错误'java.lang.VerifyError:不能从最终类继承。它甚至有可能在deftype上使用代理? – ma2s

回答

1

没有必要重新选择类型。参考“祖先”协议实现是可能的,从另一个命名空间。

user=> (ns ns1) 
nil 
ns1=> (defprotocol P (f [o])) 
P 
ns1=> (deftype T [] P (f [_] 1)) 
ns1.T 
ns1=> (f (T.)) 
1 
ns1=> (ns ns2) 
nil 
ns2=> (defprotocol P (f [o])) 
P 
ns2=> (extend-protocol P ns1.T (f [o] (+ 1 (ns1/f o)))) 
nil 
ns2=> (f (ns1.T.)) 
2 

记住ns1.Pns2.P是完全不同的猫,都被称为P