梅延涛

梅延涛的博客

他的个人主页  他的博客

什么是面向对象编程?

梅延涛  2009年10月29日 星期四 20:25 | 3020次浏览 | 27条评论

今天看到xyLinuxGroup上有同学提及面向对象的问题,我本想回复,后来发现写的有点多,就整理成一个blog出来。如果发现有错误的地方,望能斧正。
BTW: 我的个人blog是www.kermit-mei.info/blog, 以后会把技术类的blog发到这里以望有机会得到大家的指教。 谢谢!

    面相对象不是某一种语言的特性,而是一种编程思想。 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(People who)方法(参数的配偶对象)就OK了。至于which people, with who, where, when这些问题,留给那些处理具体场景的人去做就好了。

—-> 面向对象与面向过程的联系:
    面向对象和面向过程不是水火不容的,对象中是有过程的。在编程工作中,你永远无法避免对流程的处理,面向对象的思想只是给你提供了一种更合理的方式来你规 划程序中的流程,如果你是一个team leader,或者总体设计师,这将更有利于你把任务分配给你的队员。尝试这用OO思维去认识身边的事物,去规划自己的程序,很快你就会转入OOP的模 式,你会发现这种思路的确可以减轻大脑负荷。

    最后,突然想起来几年前 王聪 同学给学校提建 议,让计算机系把python作为入门语言来讲,把C语言推迟一些。我当时有些不理解,因为我们都把C看作是计算机的基础理论,把C看作是最简单易学的东 西。记得他曾跟我解释说C中暴露了太多计算机底层的东西,通常很难帮助初学者快速集中到软件开发的学习过程中。 现在我是非常赞同他这个建议,我相信,如果我们大多数人学习的第一门语言是Python,那么我们恐怕很早就养成了OOP的习惯:)

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !
梅延涛

回复 梅延涛  2009年11月02日 星期一 13:02

To 姚坚锋 14分19秒前的回复:
呵呵,我并没有误会,也谢谢你的建议。 我们都是学习的,看到不同的观点,并和大家一起讨论才能使我看到自己的不足。这点我应该感谢你才对,怎么会误会。
欢迎继续讨论!
也祝你工作开心,顺利:)

2条回复

  • 姚坚锋

    回复 姚坚锋  2009年11月02日 星期一 22:00

    BTW,在应用方面。OO天生不是游戏,但游戏天生就是OO。OO在游戏领域实在是有如鱼得水般的发挥空间。我个人觉得如果业余爱好想学习OO,做款小Java游戏就是个最有趣的课题:)

    1条回复

      • 梅延涛

        回复 梅延涛  2009年11月02日 星期一 22:13

        呵呵,我不喜欢Java,我倒是更喜欢Qt和python:)
        以前想学习java,后来学了个开始就荒废了……

        0条回复

董海

回复 董海  2009年11月02日 星期一 09:14

个人观点:大学里面讲c语言,好像不是要培养oo的,感觉是一方面熟悉编程的逻辑思维,二是配合计算机组成、系统结构、数据结构一类的课程。学不学oo,和具体学什么,要看自己兴趣和方向,感觉c还是所有程序语言的基础。

2条回复

  • 梅延涛

    回复 梅延涛  2009年11月02日 星期一 09:41

    呵呵,我倒是认为C是计算机科学的基础,而不是编程的基础——因为它本身就是为系统级开发设计的。如果那段历史我没有记错,C的诞生很大程度上都是因为要实现Unix。而学习编程,最好的开始是写应用程序:)

    1条回复

      • 董海

        回复 董海  2009年11月02日 星期一 10:39

        汗,谈到概念我就模糊了。我一直学的都很粗浅。我从开始玩别人的basic游戏才对计算机感兴趣,大学学c的时候,我自己在学vb,写些打坦克的小游戏,感觉比c好用也快速的多。但是从用c开始才开始涉及到内存,寄存器什么的,感觉如果是要对计算机系统的学习,c还是比较合适,这样估计是楼主说的计算机科学~。至于应用,我一直用pb做mis,pb搞不定的用delphi做支持,现在在学python纯属是为了用django~~。我对于编程的理解,就是编写出来n多代码(任何语言的都行),连在一起编成程序运行。简称:编程。无论他是微指令代码还是高级语言产生的伪代码。
        说c是基础是指他用的广泛,其他语言的设计之初,都会参考之,而且都提供对c库的调用 :)
        我觉得应该说:学习编写应用程序,应该从写应用程序开始。废话就是真理啊。。。
        有错包涵一下,本来就学的乱七八糟,又已经脱离程序圈n年了,嘻嘻~~

        0条回复

姚坚锋

回复 姚坚锋  2009年11月01日 星期日 23:39

我目前(较浅)的经验告诉我,引入OO实在要慎之又慎啊。模块化和过程式的思维方式并不落伍,而且更加直观。有时候单纯从功能划分的概念谈还是容易脱离实践的。实践中我们还关注是否方便调试,是否容易被理解,种种因素考虑起来后,在加上项目压力,OO反而有点捉襟见肘。除非真的有足够的深思熟虑,否则,很容易会被放弃。至少的,通过过程式编码来探路,也是不错的选择。

4条回复

  • 梅延涛

    回复 梅延涛  2009年11月02日 星期一 09:55

    刚开始构架OO的确实比较难。但是,当你真的融入进去,你会发现OO最大的特点就是可以做到提纲挈领。

    当然,代价确实是有的,最典型的就是开发效率可能会降低,对工程师的要求会比较高。 学习OO就好像学习写作文,不是一两天的功夫。 记得我高中时,那时高考流行“话题作文”。我们有个同学问语文老师:“老师,您能否给我编两个小故事,让我对所有的话题作文都能用到?” 我觉得我们老师回答得很好:“作文不是你们写数学题,可以套用公式,作文所表现出来的是你们的思想和对世界的认识。与其让我给你们两个小故事,还不如你们自己多想想,多看看来提高你们的认识和思想。久而久之,好文章自然就出来了”

    写程序有时很像写文章,当你能够写出有理有据(构架合理),而观点有符合众人口味(满足用户需求)的文章时,那你就是个好作家(构架师)了

    我不记得最近在那本上看到一句话:那些能够很快学会的东西,往往都是魔鬼……

    都是个人见解:)

    3条回复

      • 姚坚锋

        回复 姚坚锋  2009年11月02日 星期一 11:42

        说句心里话,您别见怪
        “开发效率可能会降低”,这在学校无所谓,学习嘛,低点没关系。但是放在公司工程上,是相当可怕的事情
        “写程序有时很像写文章,当你能够写出有理有据(构架合理),而观点有符合众人口味(满足用户需求)的文章时,那你就是个好作家(构架师)了。”基本上,这个比喻套用在软件的实际开发上,合理性很低。这不是简单一句“你水平不够才用不了OO”能完全解释的。其实设计质量本质上不在OO还是其它什么的,本质上在于对需求的理解和对变化的预测,不审势则宽严皆误。
        其实有很多话要说,不过怕是会引来争论了。我的观点绝非排斥OO,但我也不完全提倡,我认为OO是个选项,它是道选择题。面向对象和过程式都在不同领域获得了成功,我支持要认真学好这两种思想/技术。但是我不认可鼓励人们总用OO的思想去思考问题,那非但不是开阔视野,反而是自我束缚。

        2条回复

          • 梅延涛

            回复 梅延涛  2009年11月02日 星期一 12:03

            恩,我也不是高手,贴在这里就是希望大家斧正,相互学习的。
            很赞同你说的这些问题,我觉得我应该解释一下我的观点
            1.OO可以帮助我们更容易地构架软件——尤其是比较复杂的软件。
            2.构架合理的软件 并不一定是 OO的。
            3.我绝对没有用"OO"来衡量别人水平的意思。
            4.你最后一句话说得非常好:“(设计质量)本质上在于对需求的理解和对变化的预测,不审势则宽严皆误”,十分赞同!
            5.沿这上面这句话的理解,我更倾向于使用OO的方式去理解和构架解决需求的途径,仅此而已。
            ***6.我从来没有试图使用OO来贬低别的设计风格

            Thanks.

            1条回复

              • 姚坚锋

                回复 姚坚锋  2009年11月02日 星期一 12:42

                其实在回帖前我也稍微挣扎下,就是想只讨论技术,避免出现无谓争执的。我上面提的观点纯粹是做讨论,并没有对楼主的态度、技术水平等做任何假设。请勿误解。我订阅了一些牛人的博客,他们几乎都经历过C、C++、又C、又C++再又C的螺旋式挣扎过程,我自己没经历那么多,仅仅刚从对C++的膜拜(自从细读<C++ primer>之后)脱离出来,所以补点观点作为对楼主文章的补充。感觉这样的讨论还是可以让思路更清晰的
                讨论愉快,顺祝工作愉快。

                0条回复

徐继哲

回复 徐继哲  2009年10月31日 星期六 00:34

对象不好搞啊

0条回复

张宇杰

回复 张宇杰  2009年10月29日 星期四 23:26

大学并不只是培养程序员,很多专业都有C语言的课程,大多数人并不做程序员。一上来就摆出大堆抽象的OO,他们是接受不了的。C语言简简单单,大家知道编程语言是个啥样子就可以了。
如果是个立志做程序员的,建议还是学学C语言吧,很多高级语言都是用C写出来的,对深入理解高级语言的特性还是有帮助的。
于OO,写应用的,你可以O。像我做嵌入式的,我可没有那么多ram玩OO
玩erlang,想O都没的O。
最后,不要盲目崇拜OO,程序并不是只有OO。

8条回复

  • 孟德

    回复 孟德  2009年10月30日 星期五 13:04

    难得支持你一把,OO不是万能药,从来都不应是为了OO而OO。

    我个人认为哪种方法能快速便捷的解决问题,就用哪种方法。

    OO的好处我们要了解,它所带来的问题,我们也应该要认识到。

    0条回复

  • 梅延涛

    回复 梅延涛  2009年10月30日 星期五 09:34

    以前,王聪同学跟我说这个提法的时候,我也不赞成,我也觉得C“简简单单”,应该是个很基础的东西。不过,坦白地讲,我到现在对C的掌握水平还没有达到他两年前的程度。
    我没有说C不应该学,C是重点,也是难点,它很轻巧,但决不简单。没有两三年刻苦钻研是学不通的
    OO不是针对某种语言的,它是一种思想,是我们认识业务从而组织程序的方法,它让我们更容易管理大项目。除了Gtk+,Linux kernel中也有很多OOP之处。
    此外,我也做过嵌入式,用Qt开发过一个类似于MTK的OEM平台,但是我看不出玩OO和ram的数量有什么联系……
    谢谢你的建议!
    Have fun!

    4条回复

      • 张宇杰

        回复 张宇杰  2009年10月30日 星期五 10:03

        我写的系统,全部硬件资源只有1K RAM,没有malloc让你创建实例。对我来说,你写Qt,和写PC应用差不多了。我们的变量都是要按bit存储的。要是把一个全局变量就搞定的事,再给它封装成singleton,谁看了都受不了。

        3条回复

          • 梅延涛

            回复 梅延涛  2009年10月30日 星期五 10:23

            个人觉得,这样的环境不是嵌入式,而是单片机。嵌入式的内存至少要有MB数量级的。而单片机通常遇到的问题都是比较小的,很多东西甚至用汇编写。我以前在的公司是做遥控器的,他们的URC单片机部分也是这样。我觉得,这些工作的难度在于掌握相应硬件操作的知识,而业务上往往很简单,一个流程就OK了。面向对象的思想是为了解决业务复杂的任务的,如果业务简单,一个流程就能写完,自然没有必要凭空想个什么对象出来,而应当把注意力集中在如何节约内存上。

            2条回复

              • 孟德

                回复 孟德  2009年10月30日 星期五 13:06

                MB级的嵌入式也就是这几年的事儿,早在那之前嵌入式这个词儿就有了。

                0条回复

              • 张宇杰

                回复 张宇杰  2009年10月30日 星期五 10:41

                简单业务?
                这1K的ram是要跑我写的多线程OS的
                雷蒙德兄,以前写的文本浏览,就要求能浏览比系统总ram大N倍的文件,加载和排版速度还不能慢了。
                我只能说,兄弟,你太幸运了。

                0条回复

  • 胡钧

    回复 胡钧  2009年10月30日 星期五 04:52

    博主写得还是不错的。OO固然不是万能药,但是C同样也不是,各有各适用的场合,对初学者来说,了解OO的理念还是很重要的。

    1条回复

      • 孔建军

        回复 孔建军  2009年10月31日 星期六 08:30

        里边很多例子很生动,加深了对OO理解。

        面向过程和OO得看具体场合
        比如用C封装功能单元,再用python整合、控制。

        0条回复

边疆

回复 边疆  2009年10月29日 星期四 22:35

教育往往滞后于现实应用。最近找工作,很多公司想招PHP工程师,可是没有哪个学校把PHP当做一门课程教授。

5条回复

  • 梅延涛

    回复 梅延涛  2009年10月30日 星期五 09:41

    你工作找怎么样了?想做哪方面?
    其实,我倒是不同意大学“教育跟着市场”走的观点,大学的目的是提升学生的思想和认识的,它不是职业教育学院。学生应该在学校学习的同时,自己选一两个自己比较擅长的方向来提升自己的就业能力。 如果这种大学本身的工作做好了,这点不算难事,可惜现状并不乐观……
    从“指导思想”上讲,我们现在的大学教育和职业教育学院似乎没有什么分别。

    4条回复

      • 边疆

        回复 边疆  2009年10月30日 星期五 14:34

        应该很快就会敲定工作的事~~到时去了深圳还得你们罩着,呵呵~~

        3条回复

暂时没有评论

Zeuux © 2022

京ICP备05028076号