Revised: 浅谈OO编程中必不可少的手段:Multimethod(又名Multiple Dispatch、Generic Function)

本文探讨了Multimethod(多态方法)在面向对象编程中的重要性,它允许根据参数的实际类型来选择合适的函数执行。通过历史背景、概念解释和示例,展示了Multimethod如何在LISP和C++中实现,以及其对比重载的差异。文章指出,Multimethod是处理复杂交互和特例的有效手段,弥补了某些语言在处理多继承和交互时的不足。
摘要由CSDN通过智能技术生成

(此处为人肉维护的镜像,不保证完整复制内容到这里,也不保证及时修订错误。原文请见:http://csbabel.wordpress.com/ 翻墙请用Google Reader查看:http://csbabel.wordpress.com/feed/)

 

这可能是我写得最中规中矩的文章标题了。写这个文章的目的很傻很天真:“在網路上能夠google到的介紹multimethod的漢語文章很少”。有本很出名的书写了一笔(More Effective C++: Item 31),但很快就转而使用替代方案了。所以,我打算写一个这方面的文章给网络补充一下资源。算是遵循 “勿以善小而不为”的古训吧:)

一点历史介绍

在 上世纪的80年代中期,在LISP中出现了CLOS(读成see-loss)系统,它是Common Lisp Object System的缩写。CLOS被提出之后不久正好赶上了ANSI标准的制定。CLOS是如此之优秀,以至于它一字不改就被收录成了ANSI标准。因为它是 ANSI标准的一部分,所以基本上所有的Common LISP都带有CLOS。CLOS提供了很强大的功能,包括class定义,子类化(派生/继承),multimethod,before/after /around,重定义class,改变object的class,重新初始化object等功能(除此之外,CLOS还提供了一个强大的Meta- Object协议)。所有的这些,从功能上超过了任何其它支持OO编程的语言(就如同LISP的Condition超过了其它语言的Exception一 样)。

Multimethod是在设计CLOS的过程中提出来的。因为设计者们发现,不加入Multimethod的话,OO编程实践中 就缺少一个必要的手段。从这个角度来说,虽然Multimethod只能算CLOS中的一碟小菜,但它却是一碟很多人都需要、但是C++和JAVA就是不 给上的小菜(上的都是酸菜???)

——为什么要这么说呢?且慢慢听我道来……

很自然很舒服的面向对象

在多数教科书和随笔文章中,当讲解到面向对象技术时,一般都会举出动物的例子。我临时也编出来一个:
生物分为动物和植物;而动物可分为两栖、爬行和哺乳动物。哺乳动物中有狗有狼还有人,哺乳动物都有一个共同的行为:哺乳;两栖动物都有一个共同的属性:变态。

这个例子能很好的说明OO技术的自然性——它和人类认知中的concept正好对应[注1]:
1、Concept是一个分类方法;
2、Concept有它不同于其它concept的特有属性;
3、同属某个concept的个体有同样的属性;
4、Concept可以有层级关系,子concept拥有父concept的所有特性(但不一定能当成父concept来用,参考Liskov Subst Principle);

从这个角度来说,OO是成功的,因为它用 很自然地,符合一般人思维的方式解决了一个复杂的归类问题。(这里暂且不提interface这回事,其实真正的OO是interface的天下,但interface却不是那么“自然”的)

如果我们记住了一个概念,我们就能够了解它所代表的事物的特点和功能,从而能够很好地使用它。OO技术带来了同样强大的(复用)能力——只要知道了class名字,就可以知道object的属性和功能,并方便地使用它们。

上面的例子可以总结成这样的关系:

类别间的关系

  • 植物 is a 生物
  • 动物 is a 生物
  • 两栖动物 is a 动物
  • 爬行动物 is a 动物
  • 哺乳动物 is a 动物
  • 狼 is a 哺乳动物
  • 狗 is a 哺乳动物
  • 人 is a 哺乳动物

行为

  • 两栖动物 can 变态
  • 哺乳动物 can 哺乳


(狼、狗、人的“哺乳”行为可以从“哺乳动物”中继承而来,不需要再进行重复声明)

分类和交互:复杂性之源


世界之所以复杂,不仅仅在于事物的多样性(分类),还在于事物之间的交互。一般意义上的交互是简单的,比如下面这段程序伪码(本想用汉编的,无奈我太笨,学不会,只好用英编了)

对于打印机打印图片,我们可以这样写
function Printer.Print(RMB rmb) Action:
1. Render rmb to memory;
2. Send memory to PrinterDriver;
3. Submit to PrinterDriver
End Action;

(似 乎最近从“瘾科技”开始,不少中文站都在说钞票防伪的事情。我也来PS一杠子:世界上有几十种钞票都是打印不了的,因为有Omron的猎户座防伪专利技 术,当然,在1996发行那种50马克之前,就不会有这个问题。具体例子和应用了此技术的钞币列表请参见:http://www.ybnotes.com /cn/ennewslist.asp?id=434)

现在我们用简单的动植物模型来实际编一些程序。基于食物链方面的常识,我们可以这样总结:
1. Animal.Eat(A Plant);
2. Animal.Eat(An Animal);

于是,我们这样定义动物类型,添加一个方法,名叫“吃”:
class Animal;
class Plant;

function Animal.Eat(Animal victim) Action:

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值