Clojure中defmulti与defmethod的区别是什么?附简单示例说明
defmulti 与 defmethod 核心区别
二者是Clojure实现多重多态的配套宏,职责完全独立,必须配合使用才能生效,不存在替代关系。
核心分工
defmulti负责定义多态方法的入口与调度规则:声明方法名,同时指定调度函数——方法被调用时,会先执行这个调度函数,根据传入的入参计算出一个调度值,用来匹配对应的具体实现。你可以把它理解成方法的「总路由规则」。defmethod负责绑定具体场景的实现逻辑:它必须依附于已经通过defmulti定义好的多态方法,针对某一个特定的调度值编写对应的执行逻辑,相当于路由规则下对应的具体处理分支。
最简代码示例
我们以一个根据用户角色返回不同问候语的场景为例:
- 首先用
defmulti定义多态入口,这里我们直接取入参的:role字段作为调度值(:role本身是关键字,在Clojure中可以直接当函数用,等价于(fn [user] (:role user)))
(defmulti greet :role)
- 之后用
defmethod给不同角色绑定具体实现,同时可以定义兜底的默认分支:
;; 管理员角色的处理逻辑 (defmethod greet :admin [user] (str "您好管理员 " (:name user) ",系统当前运行状态正常。")) ;; 普通用户角色的处理逻辑 (defmethod greet :regular-user [user] (str "你好 " (:name user) ",欢迎回来。")) ;; 匹配不到任何角色时走的默认兜底逻辑 (defmethod greet :default [user] (str "访客你好,先登录再使用功能哦。"))
- 实际调用效果:
(greet {:role :admin :name "张三"}) ;; => "您好管理员 张三,系统当前运行状态正常。" (greet {:role :regular-user :name "李四"}) ;; => "你好 李四,欢迎回来。" (greet {:role :guest :name "王五"}) ;; => "访客你好,先登录再使用功能哦。"
适用场景
defmulti只需要在定义多态方法时写一次,你可以根据需求自定义任意维度的调度逻辑:既可以按参数类型调度,也可以按参数的字段值、参数个数、甚至多个参数的组合计算结果调度,灵活度远高于基于类继承的多态。defmethod用来扩展多态方法的具体分支,有多少种处理场景就写多少个,后续新增场景不需要修改已有代码,直接追加新的defmethod即可,完全符合开放封闭原则。
内容的提问来源于stack exchange,提问作者Blaze
相关产品推荐
相关产品推荐

