【问题标题】:How to reuse deftype methods in Clojure / Clojurescript?如何在 Clojure / Clojurescript 中重用 deftype 方法?
【发布时间】:2015-08-23 20:28:54
【问题描述】:

我正在尝试扩展库 DomKM/silk

具体来说,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 中这是如何完成的?

【问题讨论】:

  • Clojure 的设计者不喜欢方法的继承。我认为你不能以非常自然的方式做到这一点。您显然可以创建一个Route 对象并让MyRoute 的方法委托给Route 的方法。 deftype 创建的对象是 Java 类,因此您可以通过使用允许继承的两个 Java 互操作宏之一:proxygen-class 来做您想做的事情。 gen-class 可能是矫枉过正,所以如果你走这条路,我建议proxy。但是,这违背了 Clojure 的设计目标,因此您可能只想简单地重新实现所需的代码。
  • Route 中的函数并不大。如果你想经常这样做,你可以在 deftype 对象之外编写函数并使用 Pattern 方法调用它们。
  • @Mars 感谢您的回答!当我尝试使用代理时:(proxy [Route] [name pattern] (-match [])) 我收到错误java.lang.VerifyError: Cannot inherit from final class。甚至可以在 deftype 上使用代理吗?
  • 也许不是。我不确定。我猜它不起作用并不让我感到惊讶。虽然它没有说你不能扩展 deftypes,但 Clojure 的 datatypes 页面的“数据类型和协议是自以为是的”部分会给你这个想法。 Clojure 旨在鼓励某些类型的编程,同时保留很大的灵活性。有时,在特定情况下,灵活性比人们想要的要少,但语言充满了权衡。
  • 我最终使用了juxt/bidi。它更好地为可扩展性而设计。我已经为我的问题实现了优雅的解决方案。再次感谢

标签: clojure clojurescript


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多