Clojure中的抽象函数或函数接口?

时间:2010-01-06 07:16:16

标签: clojure

在很多场合,我有一系列功能,我想以不同的方式实现。最明显的例子是从特定数据库中抽象出来。在面向对象的语言中,您将使用一个接口:

interface DB {
  ResultSet query(String query);
  void persist(Object o);
  ...
}

在speudo代码中,我想做这样的事情:

(ns dbbackend)

(abstractfn query [q])
(abstractfn persist! [o])

然后是每个数据库的实现:

(ns dbbackend.mysql :implements dbbackend)
(defn query [q] ...)
(defn persist! [o] ...)

我并不完全清楚在功能语言中做一些类似的事情是最好的做法,特别是Clojure。我应该使用多种方法吗?

2 个答案:

答案 0 :(得分:11)

既然version 1.1 of Clojure已经发布,也许现在是时候看看未来了。

目前仅在Datatypes中提供的

protocolsthe new master branch on github可能正是您所寻找的。

(defprotocol DB
  (query   [backend query])
  (persist [backend object]))

(deftype MySQLBackend []
  DB
  (query   [query] ...)
  (persist [object] ...))

答案 1 :(得分:6)

对于协议前的Clojure版本:

界面:

(ns dbbackend)

(defmulti query
  {:arglists '([c q])}
  suitable-dispatch-fn)

(defmulti persist!
  {:arglists '([c o])}
  suitable-dispatch-fn)

实施:

(ns dbbackend.mysql
  (:requires dbbackend))

(defmethod query com.mysql.jdbc.Connection
  [c q]
  ...)

(defmethod persist! com.mysql.jdbc.Connection
  [c o]
  ...)

用法:

(ns user
  (:require dbbackend dbbackend.mysql))

(def mysql-connection (connect-to-mysql))
(query mysql-connection some-query)

您可以在ClojureQL的引擎下找到这种方法的真实示例。