版权归原作者所有,如有侵权,请联系我们

[科普中国]-面向对象

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

面向对象(Object Oriented)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。1

早期发展早期的计算机编程是基于面向过程的方法,例如实现算术运算1+1+2 = 4,通过设计一个算法就可以解决当时的问题。随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题。一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承,帮助人们实现对现实世界的抽象与数字建模。通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统。面向对象是指一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。2

面向对象的思想已经涉及到软件开发的各个方面。如,面向对象的分析(OOA,Object Oriented Analysis),面向对象的设计(OOD,Object Oriented Design)、以及我们经常说的面向对象的编程实现(OOP,Object Oriented Programming)。2

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

1.审视问题域的视角

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

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

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

2.抽象级别

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

3.封装体

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

4.可重用性

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

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

基本概念对象的含义是指具体的某一个事物,即在现实生活中能够看得见摸得着的事物。在面向对象程序设计中,对象所指的是计算机系统中的某一个成分。在面向对象程序设计中,对象包含两个含义,其中一个是数据,另外一个是动作。对象则是数据和动作的结合体。对象不仅能够进行操作,同时还能够及时记录下操作结果。3

方法是指对象能够进行的操作,方法同时还有另外一个名称,叫做函数。方法是类中的定义函数,其具体的作用就是对对象进行描述操作。3

继承简单地说就是一种层次模型,这种层次模型能够被重用。层次结构的上层具有通用性,但是下层结构则具有特殊性。在继承的过程中类则可以从最顶层的部分继承一些方法和变量。类除了可以继承以外同时还能够进行修改或者添加。通过这样的方式能够有效提高工作效率。在这里举一个例子,当类X继承了类Y后,此时的类X则是一个派生类,而类Y属于一个基类。3继承是从一般演绎到特殊的过程,可以减少知识表示的冗余内容,知识库的维护和修正都非常方便。更有利于衍生复杂的系统。4

类是具有相同特性(数据元素)和行为(功能)的对象的抽象。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。2类映射的每一个对象都具有这些数据和操作方法,类的继承具有层次性和结构性,高层次对象封装复杂行为,具体细节对该层次知识保持透明,可以减小问题求解的复杂度。

封装是将数据和代码捆绑到一起,对象的某些数据和代码可以是私有的,不能被外界访问,以此实现对数据和代码不同级别的访问权限。防止了程序相互依赖性而带来的变动影响,面向对象的封装比传统语言的封装更为清晰、更为有力。有效实现了两个目标:对数据和行为的包装和信息隐藏。1

多态是指不同事物具有不同表现形式的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。一个接口,多种方式。1

动态绑定指的是将一个过程调用与相应代码链接起来的行为。动态绑定是指与给定的过程调用相关联的代码只有在运行期才可知的一种绑定,它是多态实现的具体形式。1

消息传递:对象之间需要相互沟通,沟通的途径就是对象之间收发信息。消息内容包括接收消息的对象的标识,需要调用的函数的标识,以及必要的信息。消息传递的概念使得对现实世界的描述更容易。1

面向对象的方法就是利用抽象、封装等机制,借助于对象、类、继承、消息传递等概念进行软件系统构造的软件开发方法。1

特征(1)对象唯一性。

每个对象都有自身唯一的标识,通过这种标识,可找到相应的对象。在对象的整个生命期中,它的标识都不改变,不同的对象不能有相同的标识。2

(2)抽象性。

抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。2

(3)继承性。

继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。2

继承性是面向对象程序设计语言不同于其它语言的最重要的特点,是其他语言所没有的。

在类层次中,子类只继承一个父类的数据结构和方法,则称为单重继承。

在类层次中,子类继承了多个父类的数据结构和方法,则称为多重继承。

多重继承,JAVA、VB、NET、Objective-C均仅支持单继承,注意在C++多重继承时,需小心二义性。

在软件开发中,类的继承性使所建立的软件具有开放性、可扩充性,这是信息组织与分类的行之有效的方法,它简化了对象、类的创建工作量,增加了代码的可重用性。

采用继承性,提供了类的规范的等级结构。通过类的继承关系,使公共的特性能够共享,提高了软件的重用性。2

(4)多态性(多形性)

多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。

多态性允许每个对象以适合自身的方式去响应共同的消息。

多态性增强了软件的灵活性和重用性。2

开发方法面向对象开发方法的研究已日趋成熟,国际上已有不少面向对象产品出现。面向对象开发方法有Coad方法、Booch方法和OMT方法等。2

1、Booch方法

Booch最先描述了面向对象的软件开发方法的基础问题,指出面向对象开发是一种根本不同于传统的功能分解的设计方法。面向对象的软件分解更接近人对客观事务的理解,而功能分解只通过问题空间的转换来获得。2

2、Coad方法

Coad方法是1989年Coad和Yourdon提出的面向对象开发方法。该方法的主要优点是通过多年来大系统开发的经验与面向对象概念的有机结合,在对象、结构、属性和操作的认定方面,提出了一套系统的原则。该方法完成了从需求角度进一步进行类和类层次结构的认定。尽管Coad方法没有引入类和类层次结构的术语,但事实上已经在分类结构、属性、操作、消息关联等概念中体现了类和类层次结构的特征。2

3、OMT方法

OMT方法是1991年由James Rumbaugh等5人提出来的,其经典著作为“面向对象的建模与设计”。

该方法是一种新兴的面向对象的开发方法,开发工作的基础是对真实世界的对象建模,然后围绕这些对象使用分析模型来进行独立于语言的设计,面向对象的建模和设计促进了对需求的理解,有利于开发得更清晰、更容易维护的软件系统。该方法为大多数应用领域的软件开发提供了一种实际的、高效的保证,努力寻求一种问题求解的实际方法。2

4、UML(Unified Modeling Language)语言

软件工程领域在1995年~1997年取得了前所未有的进展,其成果超过软件工程领域过去15年的成就总和,其中最重要的成果之一就是统一建模语言(UML)的出现。UML将是面向对象技术领域内占主导地位的标准建模语言。2

UML不仅统一了Booch方法、OMT方法、OOSE方法的表示方法,而且对其作了进一步的发展,最终统一为大众接受的标准建模语言。UML是一种定义良好、易于表达、功能强大且普遍适用的建模语言。它融入了软件工程领域的新思想、新方法和新技术。它的作用域不限于支持面向对象的分析与设计,还支持从需求分析开始的软件开发全过程。2

面向对象程序设计基本思想面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为。面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这些概念面向对象的思想得到了具体的体现。1

传统的结构化设计方法的基本点是面向过程,系统被分解成若干个过程。而面向对象的方法是采用构造模型的观点,在系统的开发过程中,各个步骤的共同的目标是建造一个问题域的模型。在面向对象的设计中,初始元素是对象,然后将具有共同特征的对象归纳成类,组织类之间的等级关系,构造类库。在应用时,在类库中选择相应的类。2

面对对象程序设计是尽可能地在模拟人类的思维。通过这样的方式能够让开发的软件更加符合人类的认知,人们使用起来也能够更加顺手。并且通过应用软件能够切实地解决现实生活中的问题。面向对象程序设计使得描述问题的问题空间和问题的解决方法空间组合在一起,并且尽可能地保持一致。能够将客观世界中的抽象问题转化为具体的问题对象。3

面向对象的思维更符合人认识和思考问题的方式,面向对象的概念和应用已经超越了软件开发和程序设计,扩展到多个的领域,其中一个应用的分支就是面向对象的知识表示法。这种表示法把组成客观世界的实体抽象为数据和对数据的操作,并使用类把数据和对数据的操作封装成为一个不可分割、互相依存的整体。面向对象表示的知识更接近客观世界,表示方案更加自然,易于理解。面向对象技术良好的模块性,面向对象的系统良好的可维护性、可扩充性和可重用性等特点,正符合人们组织和管理知识库的需求。4

实现(一)程序设计语言

⒈选择面向对象语言

采用面向对象方法开发软件的基本目的和主要优点是通过重用提高软件的生产率。因此,应该优先选用能够最完善、最准确地表达问题域语义的面向对象语言。2

在选择编程语言时,应该考虑的其他因素还有:对用户学习面向对象分析、设计和编码技术所能提供的培训操作;在使用这个面向对象语言期间能提供的技术支持;能提供给开发人员使用的开发工具、开发平台,对机器性能和内存的需求,集成已有软件的容易程度。2

⒉程序设计风格

⑴提高重用性。

⑵提高可扩充性。

⑶提高健壮性。2

(二)类的实现

在开发过程中,类的实现是核心问题。在用面向对象风格所写的系统中,所有的数据都被封装在类的实例中。而整个程序则被封装在一个更高级的类中。在使用既存部件的面向对象系统中,可以只花费少量时间和工作量来实现软件。只要增加类的实例,开发少量的新类和实现各个对象之间互相通信的操作,就能建立需要的软件。2

一种方案是先开发一个比较小、比较简单的来,作为开发比较大、比较复杂的类的基础。

⑴“原封不动”重用。

⑵进化性重用。

一个能够完全符合要求特性的类可能并不存在。2

⑶“废弃性”开发。

不用任何重用来开发一个新类。

⑷错误处理。

一个类应是自主的,有责任定位和报告错误。2

(三)应用系统的实现

应用系统的实现是在所有的类都被实现之后的事。实现一个系统是一个比用过程性方法更简单、更简短的过程。有些实例将在其他类的初始化过程中使用。而其余的则必须用某种主过程显式地加以说明,或者当作系统最高层的类的表示的一部分。2

在C++和C中有一个main()函数,可以使用这个过程来说明构成系统主要对象的那些类的实例。

(四)面向对象测试

⑴算法层。

⑵类层。

测试封装在同一个类中的所有方法和属性之间的相互作用。

⑶模板层。

测试一组协同工作的类之间的相互作用。

⑷系统层。

把各个子系统组装成完整的面向对象软件系统,在组装过程中同时进行测试。2

面向对象分类面向对象方法的提取类似决策树的构思,从简到繁,先剔除其他无关信息,再经过多次筛选找出有用的地物类别,实现地物的分层提取。经过多尺度分割后,需要对分割后的单个对象进行划分,选择合适的参数或者规则将对象与其他对象区分开来,以实现各种地物的分类。5

面向对象分类提取信息的方法较传统分类方法更具有优势,前者充分考虑高分辨率影像的各种类型的特征,包括光谱、形状和纹理等空间特征。而后者是通过选择训练样本,软件自动建立判别函数对其他未识别的样本进行判断。相比而言,面向对象方法在这方面更具有针对性,目标更明确,针对的就是分割后的图斑,因此分类的结果精度更高。但如何应用好面向对象的方法,需要研究者掌握其相关的软件操作和机理,比如分割尺度的设定、特征空间的选择。5

使用面向对象分类的过程中,易受人的主观因素影响。比如特征空间的构建、特征体系的建立,在分类的后处理中也同样涉及了人机交互修正。因此,面向对象的方法虽然智能,但如果能尽量减少人工的参与,可能会提升该方法的智能化水平。5

易混概念“面向对象”和“基于对象”面向对象的三大特点(封装,继承,多态)缺一不可。通常“基于对象”是使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点。而“多态”表示为父类类型的子类对象实例,没有了继承的概念也就无从谈论“多态”。很多流行技术都是基于对象的,它们使用一些封装好的对象,调用对象的方法,设置对象的属性。但是它们无法让程序员派生新对象类型。他们只能使用现有对象的方法和属性。所以当你判断一个新的技术是否是面向对象的时候,通常可以使用后两个特性来加以判断。“面向对象”和“基于对象”都实现了“封装”的概念,但是面向对象实现了“继承和多态”,而“基于对象”没有实现这些,的确很饶口。2

“面向过程”和“面向对象”面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。2

可以拿生活中的实例来理解面向过程与面向对象,例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。2

如果是面向对象的设计思想来解决问题。面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。2

可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了多个步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。2

本词条内容贡献者为:

闫晓东 - 副教授 - 中央民族大学信息工程学院