抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

面向对象的程序设计

简介

面向对象程序设计(英语:Object-oriented programming,abbr:OOP)是一种程序设计范型,同时也是一种程序开发的方法。
对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性灵活性扩展性

面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反,
传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。

特点

面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个个体,即对象。
目前已经被证实的是,面向对象程序设计推广了程序的灵活性可维护性,并且在大型项目设计中广为应用。
此外,面向对象程序设计要比以往的做法更加便于学习,因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。

发展

面向对象是在结构化设计方法出现很多问题的情况下应运而生的。

结构化设计方法求解问题的基本策略是从功能的角度审视问题域。
它将应用程序看成实现某些特定任务的功能模块,其中子过程是实现某项具体操作的底层功能模块。
在每个功能模块中,用数据结构描述待处理数据的组织形式,用算法描述具体的操作过程。
面对日趋复杂的应用系统,这种开发思路在下面几个方面逐渐暴露了一些弱点。

1. 审视问题域的视角

在现实世界中存在的客体是问题域中的主角,所谓客体是指客观存在的对象实体和主观抽象的概念,他是人类观察问题和解决问题的主要目标。例如,对于一个学校学生管理系统来说,无论是简单还是复杂,始终是围绕学生和老师这两个客体实施。在自然界,每个客体都具有一些属性和行为,例如学生有学号、姓名、性别等属性,以及上课、考试、做实验等行为。因此,每个个体都可以用属性和行为来描述。

通常人类观察问题的视角是这些客体,客体的属性反应客体在某一时刻的状态,客体的行为反映客体能从事的操作。这些操作附在客体之上并能用来设置、改变和获取客体的状态。任何问题域都有一系列的客体,因此解决问题的基本方式是让这些客体之间相互驱动、相互作用,最终使每个客体按照设计者的意愿改变其属性状态。

结构化设计方法所采用的设计思路不是将客体作为一个整体,而是将依附于客体之上的行为抽取出来,以功能为目标来设计构造应用系统。这种做法导致在进行程序设计的时候,不得不将客体所构成的现实世界映射到由功能模块组成的解空间中,这种变换过程,不仅增加了程序设计的复杂程度,而且背离了人们观察问题和解决问题的基本思路。另外,再仔细思考会发现,在任何一个问题域中,客体是稳定的,而行为是不稳定的。例如,不管是国家图书馆,还是学校图书馆,还是国际图书馆,都会含有图书这个客体,但管理图书的方法可能是截然不同的。结构化设计方法将审视问题的视角定位于不稳定的操作之上,并将描述客体的属性和行为分开,使得应用程序的日后维护和扩展相当困难,甚至一个微小的变动,都会波及到整个系统。面对问题规模的日趋扩大、环境的日趋复杂、需求变化的日趋加快,将利用计算机解决问题的基本方法统一到人类解决问题的习惯方法之上,彻底改变软件设计方法与人类解决问题的常规方式扭曲的现象迫在眉睫,这是提出面向对象的首要原因。

2. 抽象级别

抽象是人类解决问题的基本法宝。良好的抽象策略可以控制问题的复杂程度,增强系统的通用性和可扩展性。抽象主要包括过程抽象和数据抽象。结构化设计方法应用的是过程抽象。所谓过程抽象是将问题域中具有明确功能定义的操作抽取出来,并将其作为一个实体看待。这种抽象级别对于软件系统结构的设计显得有些武断,并且稳定性差,导致很难准确无误地设计出系统的每一个操作环节。一旦某个客体属性的表示方式发生了变化,就有可能牵扯到已有系统的很多部分。而数据抽象是较过程抽象更高级别的抽象方式,将描述客体的属性和行为绑定在一起,实现统一的抽象,从而达到对现实世界客体的真正模拟。

3. 封装体

封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。该逻辑单元负责将所描述的属性隐藏起来,外界对客体内部属性的所有访问只能通过提供的用户接口实现。这样做既可以实现对客体属性的保护作用,又可以提高软件系统的可维护性。只要用户接口不改变,任何封装体内部的改变都不会对软件系统的其他部分造成影响。结构化设计方法没有做到客体的整体封装,只是封装了各个功能模块,而每个功能模块可以随意地对没有保护能力客体属性实施操作,并且由于描述属性的数据与行为被分割开来,所以一旦某个客体属性的表达方式发生了变化,或某个行为效果发生了改变,就有可能对整个系统产生影响。

4. 可重用性

可重用性标识着软件产品的可复用能力,是衡量一个软件产品成功与否的重要标志。当今的软件开发行业,人们越来越追求开发更多的、更有通用性的可重用构件,从而使软件开发过程彻底改善,即从过去的语句级编写发展到现在的构件组装,从而提高软件开发效率,推动应用领域迅速扩展。然而,结构化程序设计方法的基本单位是模块,每个模块只是实现特定功能的过程描述,因此,它的可重用单位只能是模块。例如,在C语言编写程序时使用大量的标准函数。但对于今天的软件开发来说,这样的重用力度显得微不足道,而且当参与操作的某些数据类型发生变化时,就不能够再使用那些函数了。因此,渴望更大力度的可重用构件是如今应用领域对软件开发提出的新需求。

上述弱点驱使人们寻求一种新的程序设计方法,以适应现代社会对软件开发的更高要求,面向对象由此产生。

面向对象程序设计从80年代以后成为了一种主导思想,这主要归功于C++在编写图形界面的应用。
在图形用户界面(GUI)日渐崛起的情况下,面向对象程序设计很好地适应了潮流
面向对象程序设计的思想也使事件处理式的程序设计更加广泛被应用

抽象的示例

假如我们要写一个程序模拟一只羊,使用C语言面向过程的方法,
首先想到的是开一个结构体,然后定义几个变量:

1
2
3
4
5
6
7
8
struct Sheep
{
int age;
double height;
double weight;
};

Sheep Jeff; //定义一只叫Jeff的羊

很容易,现在Jeff要跑,怎么办?
于是就用一个run函数,把Jeff作为一个参数传递来实现:

1
2
3
4
5
6
void run(Sheep sheep)
{
/* code */
}

run(Jeff);

也很容易是吧,现在我们的Jeff遇到了羊大侠,羊大侠是站着跑的,怎么描述羊大侠站着跑呢?
再写一个函数,站着跑?那假如又遇到穿鞋跑的怎么办?

这时候如果使用面向对象的方法,将跑步作为对象的成员函数,把跑步的方法作为参数传递;
这样,所有的羊都有了一种叫跑步的方法,就方便多了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Sheep 
{
public:
void run(string method="default");
void mie();//咩
private:
int age;
double height,weight;
};//定义一个Sheep类

Sheep Jeff;
Jeff.run(); //Jeff使用默认的方法跑步

Sheep YangDaXia;
YangDaXia.run("onFoot"); //羊大侠站着跑

Sheep XiYangYang;
XiYangYang.run("shoes"); //喜羊羊穿鞋跑

评论