【问题标题】:Is it possible to do datatype inheritance in Clojure?是否可以在 Clojure 中进行数据类型继承?
【发布时间】:2011-12-12 02:34:19
【问题描述】:

例如,如果我有两条不同的记录,但它们共享一些公共字段,有没有办法让两条记录共享一个公共基础记录?似乎协议只允许声明方法签名。

【问题讨论】:

  • 两个实体共享某些字段并不是在它们之间创建继承关系的充分理由。也许提供一些示例使用场景。
  • 例如,我使用记录来表示已解析的 SQL 查询。所以我有 SELECT、UPDATE、INSERT 等的记录。它们有一些共同的属性,例如“字符串”属性。当我使用多态函数处理它们时,我希望确保它们都有一些共同的属性。
  • 记录只是花哨的地图,所以我不清楚“确保它们都有一些共同的属性”是什么意思。为什么不能直接拨打(:string a-record)?此外,记录可能具有的键集与具体类型可以表达的行为不同。您要解决的实际问题是什么?

标签: clojure functional-programming


【解决方案1】:

我认为目前还不可能。

defrecord 只是一个宏,您可以使用macroexpand 来检查它的作用,例如:

(macroexpand '(defrecord User [Name Age]))

所以如果你想要这样的记录继承,你可能需要实现一个宏来做到这一点。 但我不建议这样做,因为我尽量避免继承,因为它会导致复杂性。

【讨论】:

    【解决方案2】:

    您应该针对抽象而不是特定字段进行编程,即使用协议以便记录可以共享一个公共接口。例如,如果您的所有记录类型都需要返回“字符串”属性,则使用“获取字符串”方法创建一个协议并将其扩展到每个记录类型。

    (defprotocol SQL
      (get-string [t]))
    
    (defrecord Thing [name f1 f2]
      SQL
      (get-string [t] (str name)))
    
    (defrecord AnotherThing [name f1 f2 f3 f4 blah]
      SQL
      (get-string [t] (str name)))
    

    如果您发现自己为特定协议方法创建了相同的实现,您始终可以“defn-”(非公共函数)实现并将其用作每个记录类型中的实现。

    【讨论】:

    • 如果我想创建一个共享另一个记录的某些字段的记录怎么办?比如: (defrecord a [ba bc]) (defrecord b [ba bc bd] .. 这种情况怎么处理?
    猜你喜欢
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    相关资源
    最近更新 更多