Brave Ostrich

做一只敢于面对困难的鸵鸟
Counting...

再说面试-为什么你需要知道多态(上篇)

也说面试的火爆是让我震惊的。既然标榜为一个有使命感的程序员,我觉得有责任再写一篇关于多态的文字。我无意再次挑起非技术的争议。所以关于也说面试的回复并不包含在本文中。本文是一篇纯技术文字,里面有任何谬误请不吝指出。我思考再三题目中保留了“再说面试”四个字,让整个事情有始有终,因为我说过要写一篇这样的文章。但是阅读的时候请抛开面试这个背景。

我的文章大多枯燥无味我推荐你阅读Allen Lee或者idior的文章,或者Google更多的文章(使用多态或者Polymorphism作为关键字)。

一、什么是多态?

多态是OO中最关键的特性之一(GOF语)。GOF给的定义是:The ability to substitute objects of matching interface for one another at runtime。即,在运行时刻接口匹配的对象能互换的能力。在Wikipedia上则表述为...,polymorphism lets you treat derived class members just like there parent class's members。即,多态使得你可以向对待父类的成员那样对待派生类的成员。不够直观?In practical terms, polymorphism means that if class B inherits from class A, it doesn't have to inherit everything about class A; it can do some of the things that class A does differently。即,如果class B继承自class A,它不必从class A中继承所有的东西;对于某些方法,class B可以采用与class A不同的做法和实现。

在Java和C#的语言机制中,多态表现为后绑定(或者叫动态绑定、晚期绑定),有两种形式:继承父类并重载父类中具有相同签名的方法(即overriding或者overwriting);实现抽象父类(或接口)中具有相同签名的方法。当你对由父类声明的对象调用该方法时,对应的子类中的方法就会被调用。顺便说一句overloading通常不被认为是多态机制。

在OO思想中多态隐藏具体实现,使得客户端在不了解具体实现而只了解其接口的情况下可以访问对象的方法,这使得抽象成为可能。

二、多态和抽象的关系

还是采用Wikipedia的说法吧:abstraction is a mechanism and practice to reduce and factor out details so that one can focus on a few concepts at a time。即,抽象是一种可以使你一次只关注一个事物几个概念的机制和实践。我觉得还是从反面去解释更为简单,抽象就是不具体,就可以抛开你所不关心的细节。

抽象可以使我们对对象进行更好的分类。想象一下,没有抽象,当你面对一个电灯泡的时候会多么的无奈:

  • 它有重量,这一点和石头很相似;
  • 它有体积,这一点和石头也很相似;
  • 它能发光,这一点和太阳很相似;
  • 它耗电,这一点和风扇很相似;
  • 它可以开关,这一点和门很相似。
  • ......

这一切特性都属于灯泡,所以灯泡不是石头、不是太阳、不是风扇也不是门。没有抽象,当你要打算为电灯泡写一个开关的时候,它也只能处理电灯泡对象,因为这个世界上(系统中)没有另一个东西具有电灯泡的所有特性。

有了抽象,世界将会怎样?

  • 你说电灯泡是一个有重量的对象所以它是个Weighable(可称重的),那个用来给石头称重的系统也适用于电灯泡!
  • 你说电灯泡是一个有体积的对象所以它是个Stereometriable(可以求积的),那个用来给石头算体积的系统居然也适用!
  • 你说电灯泡是一个可以开关的对象所以它是个个Switchable(可开关的),那个用来开关门的系统也可以开关电灯泡吧!
    ......现在我们可以为电灯泡的各种特性分类了,从不同的角度看待电灯泡。

这个时候你就发现你的系统对于电灯泡的依赖越来越低了,哪一天电灯泡不发光了(还叫电灯泡:)),你的开关函数居然还是不用重写呢。抽象相对于具体类要稳定,所以依赖于抽象也比依赖于具体类要稳定。

并不是说没有多态就做不到抽象,只是没有多态抽象就很难做得如此优雅。语言机制中的多态为抽象处理了大部分你不希望关心的细节。

三、多态与耦合的关系

耦合的定义:The degree to which software components depend on each other。即软件构件之间相互依赖的程度。当系统耦合越强的时候,系统越僵化、越不容易维护、不容易重用,更糟糕的是耦合越强的系统越不稳定。理论上系统中所有的构件之间都是耦合的,只是耦合的程度不同,所以我们追求解耦合实际上是追求松耦合。这篇文章称松耦合是软件的终极目标,虽然有些过激但是是非常有道理的。

解耦合的方法通常包括抽象耦合和增加层。抽象耦合:既然必须依赖,依赖于抽象总比依赖于具体要松一些(比如Observer模式)。增加层的方法有很多,在OO的机制内可以以委托的方式将部分职能转移到专门的类中(比如将创建职能转移到工厂中),而这个专门的类是一个相对稳定的类;也可以加入一个层隔离与不希望关心的构件的关系(比如Facade模式)。

抽象耦合在上一节已经讲了,与多态有着密切的联系。增加层的方法主要的idea是委托,与多态的关系不大。

太晚了今天先写到这里吧,下面可能加入一些演示多态和耦合的关系的例子,还包括多态和常见的OOD原则的关系,以及可能还会有多态和设计模式的关系。

posted on 2007-07-22 23:39 勇敢的鸵鸟 阅读(2867) 评论(25)  编辑 收藏

评论

#1楼  2007-07-23 00:54 volnet(可以叫我大V)      

多态还是挺必要的   回复  引用  查看    

#2楼  2007-07-23 07:48 老Q      

貌似楼主还是没有明白,
上篇帖子争论的焦点不是应不应该掌握这些知识(知识当然越多越好)
而是对什么样的招聘条件应该出什么样的面试提目,
主要是由楼主对现在应聘人员的素质的感叹而引发争论的。
谁都希望招来的人什么都会,什么都能,关键是现在中国软件的大环境不是很好,很多人很浮躁,这也没有办法,毕竟温饱了才能精神,大多数程序员还在为生计发愁(别告诉我在上海拿5000就叫温饱,除非你家里有房子或者一辈子不想结婚)   回复  引用  查看    

#3楼  2007-07-23 07:56 ╃小〥斌╄      

其实也有很多实践强于理论的, 何必在面试的时候把的这么严呢. 实用为主. 这不还有3个月试用期呢么. 如果自己开公司了就晓得了. 招人不是那么容易的.   回复  引用  查看    

#4楼  2007-07-23 07:59 阿武      

不理解多态就很难写出高质量的程序,对于使用OOP的程序员,理解多态我也认为是必不可少的   回复  引用  查看    

#5楼  2007-07-23 08:35 henry      

看来自己要补补基础知识!   回复  引用  查看    

#6楼  2007-07-23 08:38 JerryChou      

多态真的是面向对象的灵魂,不理解多态,面向对象就还没有入门。   回复  引用  查看    

#7楼  2007-07-23 09:11 xiao_p      

idior 的blog里面有篇文章,就是每人说句话,形容你所认识的多态,非常的经典!!!   回复  引用  查看    

#8楼  2007-07-23 09:11 路过 [未注册用户]

看了半天看不明白,难道是我太落后,不懂,还是楼主写的太深奥   回复  引用    

#9楼  2007-07-23 09:23 xiao_p      

http://www.cnblogs.com/idior/archive/2005/03/06/113727.aspx   回复  引用  查看    

#10楼  2007-07-23 09:59 航天奇侠      


多态 是指一个接口,多种形态。

因此,函数重载和虚函数都是多态的。一个是编译期决定的多态,一个在运行期决定。

多态的意义就在于统一的接口,对调用方来说,可以简单的处理编程。因为编程实际上是多个组件相互融合的过程。一个组件的设计者,不需要理解另一个组件的细节,这样将减低学习的代价,就好像你不用会制作飞机才能乘坐飞机,只需要关心他们相互连接的接口部分,学习如何使用这些接口便可。

范型也是一种编译期静态的多态编程方法,而且将多态的能力从单纯的函数提高到整个类型本身。
  回复  引用  查看    

#11楼 [楼主] 2007-07-23 10:01 肖鹏-沧浪之水      

@xiao_p
回帖不看贴:)   回复  引用  查看    

#12楼  2007-07-23 10:01 tommy [未注册用户]

不晓得你们炒什么,
不过多态没有那么神秘,几句话就搞定了
在父类里面定义一个接口,用virtual定义一个虚函数就搞定了
然后在子类里面重载就搞定了,
思想就是这样,用处很大
如果是c语言用函数指针就搞定了   回复  引用    

#13楼  2007-07-23 10:03 tommy [未注册用户]

这么简单的东东都不会还谈啥面试,羞愧不   回复  引用    

#14楼  2007-07-23 10:31 xiao_p      

@肖鹏-沧浪之水
:-)

我的文章大多枯燥无味我推荐你阅读Allen Lee或者idior的文章
>>原来是推荐了的,呵呵,我也喜欢Allen Lee的那篇多态的文章,确实很好看。   回复  引用  查看    

#15楼  2007-07-23 10:50 Anders Liu      

感觉多态这东西,会者不难,难者不会
  回复  引用  查看    

#16楼 [楼主] 2007-07-23 10:51 肖鹏-沧浪之水      

@xiao_p
:-)   回复  引用  查看    

#17楼  2007-07-23 11:22 风清扬 [未注册用户]

支持原创!圈子《日常理财》已经收藏,谢谢博主提供的精彩好文。点击进入《日常理财》不分年龄、性别、地区、职业,欢迎所有朋友们加入!http://q.163.com/qhxnwhd/   回复  引用    

#18楼  2007-07-23 13:29 YAO.NET(三千)℡      

此贴链出几个经典贴.
收藏了.
  回复  引用  查看    

#19楼  2007-07-23 17:39 kisskiki [未注册用户]

写的再多,仍然无法很好的表达你对多态的理解,能否给出具体的场景编码以对你的论述提供证据   回复  引用    

#20楼  2007-07-23 22:49 小鬼 [未注册用户]

好好学习,天天向上.   回复  引用    

#21楼  2007-07-23 23:25 Join miao      

楼主写的。。。。。   回复  引用  查看    

#22楼  2007-07-24 21:19 随风流月      

嗯,写得不错。   回复  引用  查看    

#23楼  2007-07-24 22:43 CooS      

写得不错!送你一朵小红花,聊表心意:)
  回复  引用  查看    

#24楼  2008-03-27 16:29 偶卖糕的      

所谓的面向对象,设计模式,都是为了追求松耦合,追求代码重用,这两个是基本目标,不必在意用什么手段。   回复  引用  查看    

#25楼 [楼主] 2008-03-27 16:45 勇敢的鸵鸟      

@偶卖糕的
我不赞成你的观点,我认为应当好好的研究一下有哪些手段。我在翻译一本关于设计模式的书:)   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-07-23 09:18 编辑过
 
另存  打印