4.1 面向对象程序设计
面向对象是新一代的程序开发模式,它可以模拟现实世界的事物,把软件系统抽象为各种对象的集合,以对象为最小系统单位。这更接近于人类的自然思维,为程序开发人员提供了更灵活的思维空间。
4.1.1 面向对象程序设计概述
传统的程序采用结构化的程序设计方法,即面向过程程序设计。面向过程程序设计会针对某一需求,自顶向下,逐步细化,将需求通过模块的形式实现,然后对模块中的问题进行结构化编码。也可以说,这种方法会针对问题进行求解。随着用户需求的不断增加,软件规模越来越大,传统的面向过程的开发方法暴露出许多缺点,如软件开发周期长、工程较难维护等。20 世纪80 年代后期,人们提出了面向对象程序设计(Object-Oriented Programming,OOP)的方法。面向对象程序设计将数据和处理数据的方法紧密地结合在一起,形成类,再将类实例化,形成了对象。在面向对象的世界中,不再需要考虑数据结构和功能函数,只需要关注对象就可以了。
对象是客观世界中存在的人、事、物体等实体。在现实世界中,对象随处可见,例如,路边生长的树、天上飞的鸟、水里游的鱼、路上跑的车等。不过这里所说的树、鸟、鱼、车都是对同一类事物的总称,这就是面向对象中的类(Class)。这时读者可能要问,对象和类之间的关系是什么呢?对象就是符合某种类的定义所产生的实例(Instance)。虽然在日常生活中,我们习惯用类名称呼这些对象,但是实际上看到的是类的实例对象,而不是一个类。例如,你看见树上落着一只鸟,这里的 “鸟” 虽然是一个类名,但实际上你看见的是鸟类的一个实例对象,而不是鸟类。由此可见,类只是一个抽象的称呼,而对象则是与现实生活中的事物相对应的实体。类与对象的关系如图4.1 所示。
图4.1 类与对象的关系
在现实生活中,只使用类或对象并不能很好地描述一个事物。例如,聪聪对妈妈说他今天放学看见了一只鸟,这时妈妈不知道聪聪说的鸟是什么样的。但是,如果聪聪说他看见了一只绿色的、会说话的鸟,这时妈妈就可以想象这只鸟是什么样的。这里的绿色是指对象的属性,而会说话是指对象的方法。由此可见,对象应该具有属性和方法。在面向对象程序设计中,使用属性来描述对象的状态,使用方法来处理对象的行为。
4.1.2 面向对象程序设计的特点
面向对象程序设计更加符合人的思维模式,编写的程序更加健壮和强大,更重要的是,面向对象程序设计更加有利于在系统开发时进行责任分工,能有效地组织和管理一些比较复杂的应用程序的开发。面向对象程序设计的特点主要有封装性、继承性和多态性。
1.封装性
面向对象程序设计的核心思想之一就是将对象的属性和方法封装起来,只需要让用户知道并使用对象提供的属性和方法即可,而不需要知道对象的具体实现。例如,一部手机就是一个封装的对象,当用户使用手机拨打电话时,只需要使用它提供的键盘输入电话号码,然后按下发送键即可,并不需要知道手机内部是如何工作的。
采用封装的原则可以使对象以外的部分不能随意存取对象内部的数据,从而有效地避免外部错误对内部数据的影响,实现错误局部化,大大降低查找错误和解决错误的难度。此外,采用封装的原则也可以提高程序的可维护性。当一个对象的内部结构或实现方法改变时,只要对象的接口没有改变,就不用改变其他部分。
2.继承性
在面向对象程序设计中,允许通过继承原有类的某些特性或全部特性而产生新的类,这时,原有的类被称为父类(或超类),产生的新类被称为子类(或派生类)。子类不仅可以直接继承父类的共性,而且可以创建它特有的个性。例如,已经存在一个手机类,该类包含两个方法,分别是接听电话的方法receive() 和拨打电话的方法send(),这两个方法对于任何手机都适用。现在定义一个智能手机类,该类中除了需要包含手机类中的receive()和send() 方法,还需要包含拍照的方法photograph()、视频摄录的方法kinescope() 和播放MP4 视频的方法playmp4(),这时可以先让智能手机类继承手机类,再添加新的方法,完成智能手机类的创建,如图4.2 所示。由此可见,继承性简化了对新类的设计。
3.多态性
多态性是面向对象程序设计的又一重要特征。它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一种属性或方法在父类及其各个子类中具有不同的语义。例如,首先定义一个动物类,该类中存在一个指定动物行为的方法叫喊()。然后定义两个动物类的子类,即大象类和老虎类,这两个类都重写了父类的叫喊() 方法,实现了自己的叫喊行为,并且都进行了相应的处理(如不同的声音),如图4.3 所示。
图4.2 手机与智能手机的类图
图4.3 动物类之间的继承关系
这时,在动物园类中执行使动物叫喊() 方法时,如果参数为动物类的实现,会使动物发出叫声。如果参数为大象,则会输出 “大象的吼叫声!”;如果参数为老虎,则会输出 “老虎的吼叫声!”。由此可见,动物园类在执行使动物叫喊() 方法时,不需要判断应该执行哪个类的叫喊() 方法,因为Java 编译器会自动根据所传递的参数进行判断,并根据运行时对象类型的不同而执行不同的操作。
多态性丰富了对象的内容,扩大了对象的适应性,改变了对象单一继承的关系。