3.1 编程的抽象
所有编程语言都提供一种“抽象”的方法。抽象是简化、解决问题的手段之一,从某种程度上来说,解决问题的复杂性与抽象的种类和质量直接相关。
在不同的编程语言中,抽象的程度有所不同。汇编语言是对机器底层的一种少量抽象。后来的许多“命令式”语言(如FORTRAN、BASIC和C)是对汇编语言的一种抽象。与汇编语言相比,这些语言已有了长足的进步,但它们的抽象原理依然要求我们着重考虑计算机的结构,而非问题本身的结构。因此,开发人员在使用这些语言时有一定的技术门槛,因为开发人员必须要在机器模型(“解决方案空间”)与实际解决的问题模型(“问题空间”)之间建立起一种关联关系。这个过程要求人们付出较大的精力,而且它脱离了编程语言本身的范围,造成程序代码很难编写,而且要花较大的代价进行维护。
面向对象的程序设计在此基础上跨出了一大步,程序员可利用一些工具表达“问题空间”内的元素。由于这种表达非常具有普遍性,因此不必受限于特定类型的问题。我们将问题空间中的元素以及它们在解决方案空间的表示物称作“对象”(Object)。当然,还有一些在问题空间没有对应的对象体。在面向对象编程(OOP)中,通过添加新的对象类型,程序可进行灵活调整,以便与特定问题配合。与现实世界的“对象”或者“物体”相比,编程“对象”与它们也存在共通的地方:它们都有自己的状态(state)和行为(behavior)。比如,狗的状态有名字、颜色等,狗的行为有叫唤、摇尾等。
如图3-1所示,在狗的世界里面,根据狗的状态和行为可以将狗划分为不同的种类。软件世界中的对象和现实世界中的对象类似,对象存储状态在字段(field)里,可通过方法(methods)暴露其行为。方法对对象的内部状态进行操作,并作为对象与对象之间通信的主要机制。隐藏对象内部状态,通过方法进行所有的交互,这是面向对象编程的一个基本原则——数据封装(data encapsulation)。
图3-1 狗的分类
下面以“狗”作为一个对象的建模(见图3-2)。
图3-2 “狗”作为对象的建模
狗可以通过状态(名字、颜色)来创建不同的对象,同时也提供了访问狗对象状态的方法(叫唤、摇尾)。
编程语言中的对象可以抽象为以下特征:
· 一切皆对象。可将对象想象成一种新型变量,保存着数据,但可要求它对自身进行操作。从理论上讲,可从要解决的问题本身提出所有概念性的组件,然后在程序中将其表达为一个对象。
· 程序是一大堆对象的组合。通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象“发送一条消息”。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个方法或函数。
· 每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但是在程序中却可达到任意高的复杂程度。
· 每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能接收什么样的消息”。
· 同一类所有对象都能接收相同的消息。由于类型为“狗”(Dog)的一个对象也属于类型为“动物”(Animal)的一个对象,因此一条狗完全能接收动物的消息。这意味着可让程序代码统一指挥“动物”,令其自动控制所有符合“动物”描述的对象,其中自然包括“狗”。这一特性称为对象的“可替换性”,是OOP最重要的概念之一。