

面向对象是什么
面向对象(Object Oriented,OO)的思想是软件开发中极其重要的概念和应用,它早已超越了程序设计和软件开发的范畴,延伸至数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等广泛领域。面向对象是一种对现实世界的理解和抽象的方法,它是计算机编程技术发展到一定阶段后的产物。
相比之下,面向过程(Procedure Oriented)则是一种以过程为中心的编程思想。它主要关注的是程序中正在发生的具体事情,而与谁在受影响并不直接相关。与面向对象相比,面向过程的明显区别在于缺乏封装、继承和类等特性。
无论是在软件开发还是在实际工作中,深入理解软件开发思想都是非常重要的。下面将详细介绍面向对象思想的重要性以及它在不同领域的应用。
首先,面向对象思想能够将复杂的问题分解为更小、更易理解的部分。通过将问题抽象成对象,并通过定义对象的属性和行为,我们能够更清晰地理解问题的本质,并将其分解为可管理的模块。这种分治的思想使得开发过程更加高效,同时也能提高代码的可维护性和可复用性。
其次,面向对象思想强调了封装的重要性。通过封装,我们可以隐藏对象内部的细节,仅对外暴露必要的接口。这样做的好处是可以保护对象内部的数据和状态,防止外界的误操作。同时,封装也能够提高代码的模块化程度,使得代码更易于理解和维护。
另外,继承是面向对象思想中的另一个重要概念。通过继承,我们可以创建新的对象,并从现有的对象中继承其属性和行为。这种能力使得代码的复用性大大提高,同时也能够减少代码的冗余度。继承还能够实现多态性,即同一类型的对象在不同的上下文中表现出不同的行为。
面向对象思想在实际应用中具有广泛的应用。在数据库系统中,通过面向对象的方式,我们可以将现实世界中的实体抽象成对象,并通过对象之间的关系来建立数据库的结构。这种方法能够更好地反映现实世界的模型,提高数据库的灵活性和可扩展性。
在交互式界面开发中,面向对象的思想能够将用户界面抽象成对象,并通过对象之间的交互来实现用户与系统的交互。这种方式使得用户界面的设计和开发更加灵活,同时也能够提供更好的用户体验。
在应用平台的开发中,面向对象的思想能够将平台的各个部分抽象成对象,并通过对象之间的合作来实现平台的功能。这种方式使得

从一场比赛说起
在一个软件村里
有一名资深「面向过程」程序员——老过
和一名「面向对象」信徒——阿对
同时受雇于一家挨踢店
有一天老板突发奇想
决定让这两名程序员进行一次比赛
获胜者将获得一个限量的
360 度全自动按摩椅
编程比赛开始了

不一会,他俩都写出了几乎相同的代码


老过看到新需求,微微一笑


阿对决定让新的收银方式继承 Bill 类
先在 Bill 类中新增 discount 方法
并将其开放

普通的收费方式在 discount
函数中直接返回价格
七夕节的收费方式则继承此类
在 discount 函数中实现打 77折

当老过和阿对同时将程序交给老板时

老过已经开始幻想自己将来
坐在按摩椅上的舒服日子

听到新需求
老过一阵头大
不由在「面向过程天下第一群」中吐槽道

群友也附和说
可不是嘛
就是因为老板这么多需求
才会搞得面向过程的程序一团糟
吐槽归吐槽
老过在 getPrice 函数中
再次增加了条件判断

看着越来越复杂的
Bill 类和 getPrice 方法
老过眉头紧锁
他深知事情远没有结束
中秋和国庆一过
他还需要到这个复杂的类中
删掉打折的方法
天知道老板还会再提
什么天马行空的需求
无论是新增或删除代码,在这个过长的类里做修改都是件不太愉快的事。为了在一个很长的函数中找到需要修改的位置,「面向过程」使得老过不得不浏览大量与修改无关的代码,小心翼翼地修改后,又要反复确认不会影响到类的其他部分。
老过在心底里默默地祈祷
这个类不再需要修改
提交了自己的程序
阿对收到新需求时
先是新增了中秋节支付类

再增加了国庆节支付类

「面向对象」让阿对最喜欢的一点是

有一个好消息要告诉大家!
当老板兴高采烈地说出这句话时
老过和阿对都露出了心惊胆战的表情
这句话往往意味着要更改需求

老过反抗道
但他并没有说出心里另一个小九九
实在不想再去给 Bill 类添加代码了

这次修改老过花了较长的时间才完成

看着那个只属于七夕节的 gifts 变量
老过像看着自己白衬衫上的油渍一样难受
以后每次收费时都会生成一个
只有七夕节才会用到的变量
都是因为老板的需求太奇葩
才让这个程序看起来乱糟糟的
由于这个类做了修改
本来已经测试通过的代码又得重测一遍
阿对打开了 LoversDayBill 类
将其修改如下


当老板看完老过和阿对的代码后
再次兴奋地提出新需求时
老过顿时晕了过去......
比赛真是太焦灼了
最后赢得奖励的是?
第三个参赛者
老板的傻儿子
他完全不会写程序
但他使用 Ctrl+C,Ctrl+V
拷贝了阿对的代码

面试常见考点
在面试中,面向对象的常见考察点是三个基本特征:封装、继承、多态。
- 封装
- 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
- 继承
- 继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展。通过继承创建的新类称为「子类」或「派生类」,被继承的类称为「基类」、「父类」或「超类」。
- 要实现继承,可以通过 继承和组合 来实现。
- 多态性
- 多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单说就是一句话:允许将子类类型的指针赋值给父类类型的指针。
- 实现多态,有两种方式,覆盖和重载。两者的区别在于:覆盖在运行时决定,重载是在编译时决定。并且覆盖和重载的机制不同。例如在 Java 中,重载方法的签名必须不同于原先方法的,但对于覆盖签名必须相同。
我对面向对象的理解:面向对象的编程方式使得每一个类都只做一件事。面向过程会让一个类越来越全能,就像一个管家一样做了所有的事。而面向对象像是雇佣了一群职员,每个人做一件小事,各司其职,最终合作共赢!

引申阅读
最后,我们谈谈面向对象有什么好处?
《大话设计模式》中大鸟给小菜讲的故事非常经典:
“话说三国时期,曹操带领百万大军攻打东吴,大军在长江赤壁驻扎,军船连成一片,眼看就要灭掉东吴,统一天下,曹操大悦,于是大宴众文武,在酒席间,曹操诗性大发,不觉吟道:‘喝酒唱歌,人生真爽……’众文武齐呼:‘丞相好诗!’于是一臣子速命印刷工匠刻版印刷,以便流传天下。”
“样张出来给曹操一看,曹操感觉不妥,说道:‘喝与唱,此话过俗,应改为‘对酒当歌’较好!’于是此臣就命工匠重新来过。工匠眼看连夜刻版之工,彻底白费,心中叫苦不迭。只得照办。”
“样张再次出来请曹操过目,曹操细细一品,觉得还是不好,说:‘人生真爽‘太过直接,应改问语才够意境,因此应改为‘对酒当歌,人生几何……’当臣子转告工匠之时,工匠晕倒……”
大鸟:“小菜你说,这里面问题出在哪里?”
小菜:“是不是因为三国时期活字印刷还未发明,所以要改字的时候,就必须要整个刻板全部重新刻。”
大鸟:“说得好!如果是有了活字印刷,则只需更改四个字就可,其余工作都未白做。岂不妙哉。
一、要改,只需更改要改之字,此为可维护;
二、这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用;
三、此诗若要加字,只需另刻字加入即可,这是可扩展;
四、字的排列其实可能是竖排可能是横排,此时只需将活字移动就可做到满足排列需求,此是灵活性好。”
“而在活字印刷术出现之前,上面的四种特性都无法满足,要修改,必须重刻,要加字,必须重刻,要重新排列,必须重刻,印完这本书后,此版已无任何可再利用价值。”
小菜:“是的,小时候我一直奇怪,为何火药、指南针、造纸术都是从无到有,从未知到发现的伟大发明,而活字印刷仅仅是从刻版印刷到活字印刷的一次技术上的进步,为何不是评印刷术为四大发明之一呢?原来活字印刷是思想的成功,面向对象的胜利。”