Programming Clojure学习笔记——多重方法

8.2 定义多重方法
定义多重方法使用defmulti:
(defmulti name dispatch-fn)
name为多重方法的名字,Clojure将针对方法的参数调用dispatch-fn来选择多重方法的一个特定的方法(实现)。

考虑前一节的my-print函数,它只有一个参数,即需要打印的东西,可以基于参数的类型选择特定的实现。因此dispatch-fn必须是一个能返回参数类型的函数,Clojure内置函数class刚好满足条件。使用class函数来创建一个名为my-print的多重方法:
(defmulti my-print class)
这时还得为多重函数my-print提供特定的方法实现,可以通过defmethod来为其添加特定方法实现:
(defmethod name dispatch-val & fn-tail)
name为特定实现所属多重方法的名称,Clojure通过dispatch函数返回值与dispatch-val进行匹配来选择特定方法,fn-tail包含参数和函数体。
创建一个匹配字符串的my-print方法实现:
(defmethod my-print String [s] (.write *out* s))
创建一个匹配nil的my-print方法实现:
(defmethod my-print nil [s] (.write *out* "ni"))

多重方法的方法实现可以在代码的任何地方出现,也可以在不修改原来代码的情况下,随时添加新的方法实现

Dispatch能自动识别继承
多重方法dispatch能够识别Java继承。举例说明创建my-print的一个实现处理Number类型的参数:
(defmethod my-print Number [n] (.write *out* (.toString n)))
该方法对integer类型的参数,同样有效:
user=> (my-println 42) # 输出42

Clojure内部使用isa函数来识别继承关系:
(isa? child parent)
它直到integer是一个Number:
(isa? Integer Number) # 输出true

多重方法默认实现方法
可以使用:default作为dispatch值来处理不与任何实现方法匹配的方法调用。
如下使用:default创建一个my-print方法,打印Java对象toString值,并使用#<>括起来:
(defmethod my-print :default [s]
     (.write *out* "#<")
     (.write *out* (.toString s))
     (.write *out* ">"))

如果不幸:default在领域里已经有某些特殊的含义,你可以使用下面的方式创建多重方法,指定默认方法实现:
(defmulti name dispatch-fn :default default-value)
然后通过default-value来标识你自己的默认实现方法,如:
(defmulti my-print class :default :everything-else)
(defmulti my-print String [s] (.write *out* s))
(defmethod my-print :everything-else [_] (.write *out* "Not implemented yet..."))

多重方法依赖第一个参数的类型进行分发处理,是最常见的分发,在其他面向对象语言中,这是唯一的一种动态分发,名为多态。但是Clojure的分发比这要普通的多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值