与多态性相关的"Clojure支持多个分类法"是什么意思?



我一直在阅读此处的"Clojure原理":

http://clojure.org/rationale

多态性部分显示:

Clojure multimethods decouple polymorphism from OO and types
   Supports multiple taxonomies
   Dispatches via static, dynamic or external properties, metadata, etc

这里的"支持多个分类法"是什么意思?事实上,在这种情况下,什么是分类法?感谢

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"]

在上面的代码中,创建了两个组织系统——一个是颜色,另一个是腿。这两种分类法都是有效的,同一个对象可能会根据使用的分类法而落入不同的位置。

多方法也可以使用层次结构进行调度(请参阅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"]

在这里,同一只小猫是两个层次的成员——一个是驯化,另一个是遗传学,它可以通过适当的方法来解决。

此外,即使设置为多方法,通过derive创建的关系也支持多重继承,这与Clojure所基于的jvm类继承不同:

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

Clojure与许多其他函数式语言一样,利用松散类型提供了实现参数多态性的简单方法。这基本上意味着,可以以一种不关心给定参数的值类型的方式来构造单个方法。

concat方法为例。它接受任意数量的不同形式的参数,并将它们放入一个列表中,如下所示:

user=> (concat [:a :b] nil [1 [2 3] 4])
(:a :b 1 [2 3] 4)

因为不需要为参数声明类型,所以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"

greeting方法从映射返回与返回正确对应值的"English""French" defmethod匹配的"language"值。希望您能看到这个概念如何潜在地应用于任何类型的数据或对象结构。这种强大的多态性思想正是Clojure开发人员试图在基本原理页面中展示的。

最新更新