如何在Clojure / Clojurescript中重用deftype方法?

6
我正在尝试扩展库DomKM/silk。具体来说,有一个实现协议Patterndeftype Route,它具有方法实现,我想在我的自定义实现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互操作宏之一来实现您想要的功能:proxygen-classgen-class可能过于复杂,因此如果您选择这条路线,我建议使用proxy。然而,这与Clojure的设计目标相违背,因此您可能希望简单地重新实现所需的代码。 - Mars
Route 中的函数并不是很大。如果您想要经常这样做,可以编写 deftype 对象外部的函数,并使用 Pattern 方法调用它们。 - Mars
@Mars 感谢您的回答!当我尝试使用代理:(proxy [Route] [name pattern] (-match []))时,我遇到了一个错误 java.lang.VerifyError: Cannot inherit from final class。在deftype上使用代理是否可行? - ma2s
也许不是。我不确定。我猜这并不令人惊讶它不起作用。虽然它没有说你不能扩展deftypes,但Clojure的datatypes页面中的“Datatypes and protocols are opinionated”部分会给你一个想法。Clojure旨在鼓励某些类型的编程,同时保留很大的灵活性。有时在特定情况下灵活性比想象中要少,但语言充满了权衡。 - Mars
1
我最终使用了juxt/bidi。它的设计更适合可扩展性。我已经用它实现了优雅的解决方案。再次感谢。 - ma2s
жҲ‘жІЎжңүд»”з»Ҷ研究иҝҮпјҢдҪҶжҲ‘зӣёдҝЎPotemkinеҸҜд»ҘдҪҝз”Ёdef-abstract-typeжқҘе®һзҺ°иҝҷдёҖзӮ№гҖӮ - ClojureMostly
1个回答

2

不需要重新定义类型。可以从另一个命名空间引用“祖先”协议实现。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接