Clojure

執行時期多型

使用執行時期多型的系統較容易變更和延伸。Clojure 支援多型的方式有數種

  • Clojure 執行時期中的大多數核心基礎架構資料結構都是由 Java 介面定義的。

  • Clojure 支援使用 proxy 在 Clojure 中產生 Java 介面的實作 (請參閱 JVM 主控).

  • Clojure 語言支援使用 multimethod 沿著類別和自訂階層進行多型。

  • Clojure 語言也支援使用 protocols 進行更快速的型態多型 (但僅限於類別多型,以利用 JVM 現有的呼叫功能)。

Clojure 多重方法是一種簡單但強大的執行時期多態機制,沒有物件導向、類型和繼承的陷阱。執行時期多態的基本概念是,單一函數標識符會根據呼叫的某個值,傳送至多個獨立定義的函數定義。對於傳統的單一傳送物件導向語言,該值是「接收者」或「this」的類型。CLOS 通用函數將傳送值擴充至多個引數的類型或值的複合,因此是多重方法。Clojure 多重方法更進一步,允許傳送值成為引數的任意函數結果。Clojure 不支援實作繼承。

多重方法使用 defmulti 定義,它採用多重方法的名稱和傳送函數。方法使用 defmethod 獨立定義,傳遞多重方法名稱、傳送和函數主體。

(defmulti encounter (fn [x y] [(:Species x) (:Species y)]))
(defmethod encounter [:Bunny :Lion] [b l] :run-away)
(defmethod encounter [:Lion :Bunny] [l b] :eat)
(defmethod encounter [:Lion :Lion] [l1 l2] :fight)
(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)
(def b1 {:Species :Bunny :other :stuff})
(def b2 {:Species :Bunny :other :stuff})
(def l1 {:Species :Lion :other :stuff})
(def l2 {:Species :Lion :other :stuff})
(encounter b1 b2)
-> :mate
(encounter b1 l1)
-> :run-away
(encounter l1 b1)
-> :eat
(encounter l1 l2)
-> :fight

多重方法在各方面都是函數,例如可以傳遞給 map 等。

與介面類似,Clojure 協定只定義函數規格(沒有實作),並允許類型實作多個協定。此外,協定開放給後續動態擴充,以支援新的類型。協定僅限於傳送至類別類型,以利用多型方法呼叫的原生 Java 效能。如需更多詳細資訊,請參閱 協定 頁面。