面向对象编程技术

在现实生活中,我们必须弄明白我们所面对的大量的事实以及观念。为此,我们需要从表面细节中抽象出其内在逻辑,发现事物的本质。抽象法可以帮助我们揭示事物的因果,结构和表现形式,区分主要和次要。面向对象编程提供了一种对您所操作的数据进行抽象的方法—而且,面向对象编程将数据和对数据的操作组合到一起,从而使数据具有了行为。

本部分包含如下内容:


数据和操作

传统的编程语言通常划分成两个部分—数据和对数据的操作。数据是静态的,不变的,除非通过操作来改变它。对数据操作的函数并不保留上一次操作时数据的状态,它们的作用仅体现在操作数据上。

很明显,这种划分是基于计算机的工作方式,所以您很难忽视它。和无处不在的原料和能量以及名词和动词的划分一样,它构成了程序的本质。从某种意义上说,所有的程序员—即使是面向对象的程序员—都是工作在数据结构之上,他们的程序也会使用和定义函数来操作数据。

对于面向过程编程语言例如C来说,这几乎就是一切了。语言本身可能为组织数据和函数提供了多种支持,但是本质上仍然是分成数据和操作两个部分。函数和数据结构是设计的基本元素。

面向对象编程当然不会这样来划分,而是在更高的层次重新组织。它把操作和数据组合为一个模块单元叫做对象 ,并且把对象组成一个结构化的网络来完成一个程序。在面向对象的编程语言中,对象和对象间的交互才是设计的基本元素。

每个对象都具有状态(数据)和行为(对数据的操作)。也就是说,它们和物理实体并没有太大区别。一台机械装置例如怀表、钢琴如何体现自己的状态和行为是显而易见的,然而几乎每样功能性的物体都能够体现自己的状态和行为。即使一个普通的瓶子也会有状态(瓶子有多满,瓶子是否已经打开,瓶子所装的液体温度多少)和行为(以不同的流量倒出所装液体,盖上或者打开,加热或者制冷)。

正是这种与实物的相似性赋予了对象强大的能力和吸引力。这些对象不仅可以对现实系统的组件建模,也能够胜任软件系统中的同样的角色。


接口和实现

编写一个程序,您需要对问题进行抽象, 并使用程序将其表达出来。这正是编程语言帮您做的工作。编程语言可以帮助您对抽象后的问题进行编码从而使得程序的编写和设计过程更为简单。它使您只用关注您所写的代码和程序的架构而无需关心表面的细节。

所有的程序语言都提供了对抽象后的问题进行编码的方法。本质上,这些方法就是怎样分离并隐藏实现细节,然后至少在某种程度上,提供给这些细节一个公共的接口—就像机械装置将它的表面和内部的构造分离一样—如图"接口和实现"所示。


图 2-1 接口和实现





随着对该装置的观察角度不同,您所关注的层面也不同。作为一个实现者,您需要关心它是由什么构成并且怎样工作的。作为一个用户,您仅需要关心它是什么并且它能够做什么。您可以略过那些具体的细节而从更高层次来考虑问题。

在C语言中,程序的基本单位是结构体和函数,这两者从不同的方面隐藏了具体实现细节。
从数据方面,C中的结构体把数据组合成一个更大的单位从而可以象一个单独的实体一样对它进行操作。尽管有时候代码需要访问结构体内部的数据,但程序一般都将结构体作为一个单独的数据实体来对待—而不是数据的集合。结构体能包含另一个结构体,从而组成复杂的数据结构。

在现代C语言中,结构体中的数据元素位于该结构体的名字空间—也就是说,结构体内的元素名字不会和结构体外的同名元素冲突。 划分名字空间对保证实现细节和接口的分离来说是非常必要的。例如,试想一下,在一个大规模的程序中给每个数据元素赋予一个不同的名字并且保证新的命名不会和已存在的命名冲突是一件多么巨大的工作。
从过程方面,函数封装了一些可以重复使用而不用重新实现的行为(操作)。和结构体的数据元素一样,函数中局部变量也处于该函数自己的名字空间。函数可以调用其他的函数,从而组成复杂的逻辑。

函数是可复用的。一旦函数被定义,则可以不限次的调用而无需再重新实现。一些被广泛使用的函数可能被收集在函数库中并且在不同的应用程序中被重用。用户只需要函数的接口,而不需要知道函数的实现。

然而,和结构体中数据元素不同的是,函数并没有划分不同的名字空间。每个函数的名字必须唯一。尽管函数是可复用的,但函数名不是。

C语言中的结构体和函数都能够帮助您对问题进行抽象,但是它们仍然区分了数据和对数据的操作。在面向过程的编程语言中,问题要么被抽象成数据,要么被抽象成操作。您的程序总是按照计算机的工作方式去设计。

面向对象的语言没有抛弃结构体和函数的优点—它更深入了一步,将问题抽象成更高层次的单位,从而隐藏了函数和数据之间的交互。

例如,假设您有一组函数(接口)作用于某个特定的数据结构。您希望这些数据结构和接口无关从而使得这些函数尽可能的易于使用,所以提供了一些额外的函数来管理这些数据。所有对该数据结构的操作—分配内存空间,初始化,获取数据,更改数据,更新数据,释放内存空间—都通过这些额外的函数来进行。用户所需要做的只是以该数据结构为参数调用这些函数。

这样,该数据结构对其他的程序员来说是不透明的,他们无需关心该数据结构的内部构成,从而专注于函数的功能,而不是该数据结构。到现在为止,您已经完成了创建对象的第一步。

下一步就是在编程语言中支持这一想法并且完全隐藏掉数据结构从而无需在函数中作为参数来回传递。该数据结构成为一个内部的实现细节,暴露给用户的是函数接口。因为对象完全封装(隐藏)了内部数据,所以用户只用考虑对象的行为。

有了这一步,这些函数的接口变得更为简单。调用者无需知道函数是怎么实现的(使用了什么数据)。现在我们可以把它称之为”对象“。

被隐藏的数据结构把所有的访问自己的函数联合在一起。所以,一个对象不是一些随机选择的函数的集合,而是数据结构支持的一组相关的行为。要使用一个对象的函数,您必须首先创建一个对象(从而分配了内部数据结构),然后告诉这个对象执行哪个函数。从这时开始,您只需考虑这个对象能做什么,而不用单独的考虑这些函数能做什么。

从函数和数据结构到对象行为的过程就是学习面向对象编程的精髓。可能一开始有点不习惯,但如果您有了一定的面向对象编程经验后,您会发现面向对象更符合我们思考问题的自然方式。日常的编程术语中充满了对现实世界的模拟—表单,容器,表格,控制器,甚至管理者,将这些做为程序对象来实现也是自然而然的事情。

不同的编程语言对问题抽象的方式也不同。您不应关心和当前问题无关的细节。

例如,如果您总是要求相应的过程必须处理相应的数据,则您将需要知道底层的实现细节。尽管您仍然可以在更高的层次抽象问题,然而,从设计到实现的区别可能变得很细微—而且程序规模越大,越复杂,则设计越困难。

通过对问题不同层次的抽象,面向对象语言向您提供了更大的词汇表和更丰富的编程模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值