在很多场合,我有一系列功能,我想以不同的方式实现.最明显的例子是从特定数据库中抽象出来.在面向对象的语言中,您将使用一个接口:
interface DB {
ResultSet query(String query);
void persist(Object o);
...
}
Run Code Online (Sandbox Code Playgroud)
在speudo代码中,我想做这样的事情:
(ns dbbackend)
(abstractfn query [q])
(abstractfn persist! [o])
Run Code Online (Sandbox Code Playgroud)
然后是每个数据库的实现:
(ns dbbackend.mysql :implements dbbackend)
(defn query [q] ...)
(defn persist! [o] ...)
Run Code Online (Sandbox Code Playgroud)
对我来说,最好的做法是用功能语言,特别是Clojure做类似的事情,这一点并不完全清楚.我应该使用多种方法吗?
Jon*_*nas 11
现在已经发布了Clojure的1.1版,也许是时候看看未来了.
数据类型和协议目前仅在github上的新主分支中可用,可能正是您正在寻找的.
(defprotocol DB
(query [backend query])
(persist [backend object]))
(deftype MySQLBackend []
DB
(query [query] ...)
(persist [object] ...))
Run Code Online (Sandbox Code Playgroud)
对于预协议Clojure版本:
界面:
(ns dbbackend)
(defmulti query
{:arglists '([c q])}
suitable-dispatch-fn)
(defmulti persist!
{:arglists '([c o])}
suitable-dispatch-fn)
Run Code Online (Sandbox Code Playgroud)
实施:
(ns dbbackend.mysql
(:requires dbbackend))
(defmethod query com.mysql.jdbc.Connection
[c q]
...)
(defmethod persist! com.mysql.jdbc.Connection
[c o]
...)
Run Code Online (Sandbox Code Playgroud)
用法:
(ns user
(:require dbbackend dbbackend.mysql))
(def mysql-connection (connect-to-mysql))
(query mysql-connection some-query)
Run Code Online (Sandbox Code Playgroud)
您可以在ClojureQL的引擎下找到这种方法的真实示例.