在很多场合,我有一系列功能,我想以不同的方式实现。最明显的例子是从特定数据库中抽象出来。在面向对象的语言中,您将使用一个接口:
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。我应该使用多种方法吗?
答案 0 :(得分:11)
既然version 1.1 of Clojure已经发布,也许现在是时候看看未来了。
目前仅在Datatypes中提供的 protocols和the new master branch on github可能正是您所寻找的。 p>
(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的引擎下找到这种方法的真实示例。