Kermit’s Gossip

来源:百度文库 编辑:神马文学网 时间:2024/04/27 13:27:03
今天看到xyLinuxGroup上有同学提及面向对象的问题,我本想回复,后来发现写的有点多,就放到这里吧。如果发现有错误的地方,可以在此回复指正,谢谢!
面相对象不是某一种语言的特性,而是一种编程思想。 C也是可以编写出很好的OO代码的,Gtk+就是典型的例子。
我们很多初学者往往一提到面相对象就一头雾水,我觉得很大程度上都是因为我们学习的第一们语言是C,而struct总是在后面才讲到,用C实现继承技术需要一定技巧,一般的教材上都不讲,加之我们刚开始遇到的学习程序有很小,很容易一个简单的流程就处理完了……这所有因素结合在一起,就导致我们用程序解决问题的思维有了 一个定式: 任务是什么流程? 把流程切割成哪几块? 每块定义成什么函数?
等到我们所面临的业务比较复杂了,原本线状的流程图也就变成一个可怕的网状流程,我们根本找不到哪里是开始,哪里是结束,自然就无从下手……
个人觉得,面向过程(或面向函数)的思维方式,其实就是程序员要把整个业务画到一个流程图中,因果关系,逻辑关系要搞得很清楚。你们回忆一下,你们在学习C语言时,是不是很乐意在纸上或者脑子里画这种流程图来帮你们利清楚思路?这种思维的最大问题在于,当这张流程图变成一张流程网的时候,人的脑容量是不可能对之进行管理的,而且,维护程序的时候也必须同样面对这张“网”,这对于维护代码的同事而言,简直就是一场灾难。
——最初,我们只想得到一根“线”来帮助我们贯穿始终,但后来这条“线”越来越长,又多了许多分支,于是变成了一张网;最终,网越来越密,等到我们无法继续时,我们才发现,我们一直都在作茧自缚:)
下面,我举个例子来说明面向过程和面向对象的一点区别。
假设在一段游戏的代码中,有这样一个场景:有1000吨的货物,要从西安运到北京。
面向过程(面向函数)的思维会这样思考:恩,从西安到北京这一路上会有那些障碍?那些路是用车送的,那些路是用人送的,可能有什么突发情况(山洪,泥石流,土匪打劫)……这些东西你有一个想错了,就是一个bug,有一个没想到的,就是一个潜在的bug……更要命的是,你要修正一个这样的bug,要在每个分支上都修改一遍。
而面向对象(OO)的思维则会这样思考:
—->定义类(封装性):恩,这么复杂的送货任务,总要有个人来做吧:) OK,是得搞个押运员去弄。 于是,要定义一个类:Escort。 稍后给它定义好新的方法:)
—->继承:这个押运员得是个人吧,应该有人的一切属性(如眼耳鼻舌,受想行识),好吧,我不用重新实现这些,游戏中一般都有People的角色,从那里继承就好了,于是,Escort就成了People的子类,他可以享用People的一切属性和方法——这就是继承。你不必为了Escort再重写那么多代码,因为已经有写好可用的了。要知道,People中很多方法在Escort中都是用得到的。
—->定义方法:好了,现在再分析一下Escort可能遇到的问题,以及他面对问题所应具有的解决问题的能力——就是他具有的方法。 “山洪?地震?泥石流?” 这些都是自然灾害,没办法避免,OK,那就绕道而行吧!得,第一个方法有了: Escort::choseWay()。 那么,他怎么知道哪里有自然灾害导致道路不通呢? “废话!听广播,看电视撒!”哦,很好,我们的Escort是从People中继承下来的,而这些方法我们都在People中实现了,这里已经没有多少事情做了。
—->多态有什么用?
现在我们假设有这样一种情况:所有的人(People)都可能半路遇到凶残的土匪,如果是你,你会怎么做? 我想一般人都会跟我一样:把钱给人家保命。所以,People中“处理土匪”的方法会这么定义:{弃财保命}。但是,作为一个Escort,你要是把货物都丢了,这个Escort就失败了,你们看看《闯关东》上的垛爷怎么做的:“爷们儿,碰了,这几个钱个林子后面的弟兄们买酒喝”。所以,我们的Escort要重新实现“处理土匪”的方法,就是 { 按照道儿上的规矩,打手势,弃小财而保全货物 }。
现在,我们知道,所有的people都具有“处理土匪”的能力,但是不同的people对土匪的处理行为可能会不同。再设想一下,某个山寨区域的代码是由另外一个同事,甚至另外一个团队编写的,他们只知道他们的土匪面对的对象类型都是People,他们不知道People还有没有子类,还有多少子类等等。幸运的是,OO的多态可以让这些设计山寨区域的团队不必考虑这些问题,他们只需要调用People的“处理土匪”方法,在运行时刻,程序会自动根据实际传入的对象来判断最终要真正执行的方法。
这种调用同一基类接口,在运行时根据对象来执行相应对象类型中所定义的方法的行为就是多态。注: 这个定义是我自己给出的,如果您发现有不正确,请指出来,也方便我即使改正。在很多C++教程中,多态的定义多为:“多态是指父类指针调用子类方法。”我觉得这种说法欠妥,多态是很多OO语言的共性,比如python中没有指针,但照样有多态的功能。不过python是直接根据对象类型识别的,所以这个概念在python的教材中淡出了。
—->面向对象的扩展性:
相对于面向过程(函数)的编程思想,面向对象思想更易于编写易扩展空间。比如上面的“送货”的例子,这个游戏可能只是一个战争类游戏。后来,老板为了刺激消费,要把它像《虚拟人生》那样的方向改进。具体一点,老板希望游戏中可以有一些性方面的设计——这个虽然不健康,但是在市场上却往往很管用。这个时候,你不必在每个人,每个分支上都添加关于性方面的代码,你只需要给People类添加一个People::makeLove(Peoplewho)方法(参数的配偶对象)就OK了。至于which people, with who, where,when这些问题,留给那些处理具体场景的人去做就好了。
—->面向对象与面向过程的联系:
面向对象和面向过程不是水火不容的,对象中是有过程的。在编程工作中,你永远无法避免对流程的处理,面向对象的思想只是给你提供了一种更合理的方式来你规划程序中的流程,如果你是一个teamleader,或者总体设计师,这将更有利于你把任务分配给你的队员。尝试这用OO思维去认识身边的事物,去规划自己的程序,很快你就会转入OOP的模式,你会发现这种思路的确可以减轻大脑负荷。
最后,突然想起来几年前王聪同学给学校提建议,让计算机系把python作为入门语言来讲,把C语言推迟一些。我当时有些不理解,因为我们都把C看作是计算机的基础理论,把C看作是最简单易学的东西。记得他曾跟我解释说C中暴露了太多计算机底层的东西,通常很难帮助初学者快速集中到软件开发的学习过程中。现在我是非常赞同他这个建议,我相信,如果我们大多数人学习的第一门语言是Python,那么我们恐怕很早就养成了OOP的习惯:)