我一直在阅读'Clojure Rationale':
http://clojure.org/rationale
Run Code Online (Sandbox Code Playgroud)
在多态性部分,它读取:
Clojure multimethods decouple polymorphism from OO and types
Supports multiple taxonomies
Dispatches via static, dynamic or external properties, metadata, etc
Run Code Online (Sandbox Code Playgroud)
这里的'支持多种分类法'是什么意思?事实上,在这种情况下,什么是分类?谢谢
user> (defmulti shade :color)
nil
user> (defmethod shade :black [_] "darkest of darks")
#<MultiFn clojure.lang.MultiFn@22b90f93>
user> (defmethod shade :white [_] "all frequencies are reflected")
#<MultiFn clojure.lang.MultiFn@22b90f93>
user> (defmulti movement :legs)
#'user/movement
user> (defmethod movement 2 [_] "walks on hind legs")
#<MultiFn clojure.lang.MultiFn@13b58075>
user> (defmethod movement 4 [_] "proceeds on all fours")
#<MultiFn clojure.lang.MultiFn@13b58075>
user> ((juxt movement shade) {:name "cat" :legs 4 :color :black})
["proceeds on all fours" "darkest of darks"]
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,创建了两个组织系统 - 一个是颜色,另一个是腿.这两种分类法同样有效,并且根据所使用的分类法,同一对象可以分为不同的位置.
多方法也可以使用层次结构进行调度(参见derive和相关函数),其中每个层次结构可以并行共存(与类层次结构的统一视图不同).
user> (derive ::manx ::cat)
nil
user> (defmulti favorite-treat :species)
#'user/favorite-treat
user> (defmethod favorite-treat ::cat [_] "Tuna")
#<MultiFn clojure.lang.MultiFn@264d27e6>
user> (derive ::indoor ::domestic)
nil
user> (defmulti activity :tameness)
#'user/activity
user> (defmethod activity ::domestic [_] "window watching")
#<MultiFn clojure.lang.MultiFn@1654bf3f>
user> ((juxt favorite-treat activity) {:species ::manx :tameness ::indoor})
["Tuna" "window watching"]
Run Code Online (Sandbox Code Playgroud)
在这里,同一个小猫是两个等级的成员 - 一个是归化,另一个是遗传,并且可以通过适当的方式解决其方法.
此外,甚至设置asid multimethods,通过derive支持多重继承创建的关系,不像jvm类heirarchy Clojure建立在:
user> (derive ::foo ::bar)
nil
user> (derive ::foo ::baz)
nil
user> (derive ::quux ::foo)
nil
user> (isa? ::quux ::foo)
true
user> (isa? ::quux ::bar)
true
user> (isa? ::quux ::baz)
true
user> (isa? ::bar ::baz)
false
Run Code Online (Sandbox Code Playgroud)
Clojure 与许多其他函数式语言一样,利用松散类型来提供实现参数多态性的简单方法。这基本上意味着单个方法可以以不关心给定参数的值类型的方式构造。
以方法为例concat。它接受任意数量的不同形式的参数,并将它们放入一个列表中,如下所示:
user=> (concat [:a :b] nil [1 [2 3] 4])
(:a :b 1 [2 3] 4)
Run Code Online (Sandbox Code Playgroud)
因为不需要声明参数的类型,所以concat可以用这样一种方式编写:您可以提供任何类型的参数(向量、函数、关键字、字符串等),并且它将以类似的方式作用于它们。
Clojure 的多方法允许您通过使用元数据或其他属性来确定处理给定参数的适当方法,从而在可能具有完全不同结构(即分类法)的 Java 对象上支持此概念。请参阅以下示例(取自defmulti):
(defmulti greeting
(fn[x] (x "language")))
(defmethod greeting "English" [params]
(str "Hello! " (params "id")))
(defmethod greeting "French" [params]
(str "Bonjour! " (params "id")))
=>(greeting {"id" "1", "language" "English"})
"Hello! 1"
=>(greeting {"id" "2", "language" "French"})
"Bounjour! 2"
Run Code Online (Sandbox Code Playgroud)
该方法从映射中greeting返回与返回正确对应值的 def 方法匹配的值。希望您能够看到这个概念如何潜在地应用于任何类型的数据或对象结构。Clojure 开发人员试图在基本原理页面中展示这种强大的多态性思想。"language""English""French"