第二章2124.docx

上传人:b****5 文档编号:5628932 上传时间:2022-12-29 格式:DOCX 页数:16 大小:69.09KB
下载 相关 举报
第二章2124.docx_第1页
第1页 / 共16页
第二章2124.docx_第2页
第2页 / 共16页
第二章2124.docx_第3页
第3页 / 共16页
第二章2124.docx_第4页
第4页 / 共16页
第二章2124.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

第二章2124.docx

《第二章2124.docx》由会员分享,可在线阅读,更多相关《第二章2124.docx(16页珍藏版)》请在冰豆网上搜索。

第二章2124.docx

第二章2124

第二章面向对象的基本概念和程序设计

面向对象的概念主要来自面向对象的程序设计语言,因此面向对象的基本概念与面向对象的程序设计语言有着天然的联系,因此在本章中首先介绍面向对象的基本概念,然后利用面向对象的程序设计语言来说明面向对象的基本概念。

本章的目的不是介绍某种面向对象的程序设计语言,因此对面向对象程序设计语言有兴趣的同学,可以参考相应的语言参考书目。

2.1简介

本章将讨论面向对象的基本概念,同时利用面向对象的程序设计语言来说明这些重要概念。

由于面向对象的概念来自面向对象的程序设计语言,因此该章也重点讨论面向对象的程序设计语言。

面向对象的程序设计主要是指利用面向对象的基本概念进行程序设计。

面向对象程序设计的主要优点是增强了代码重用,并且比其它类型的程序设计语言更易于理解与维护。

面向对象的程序设计语言至少支持以下概念:

封装的对象、类及实例、继承、多态及动态联编。

虽然这些概念对于面向对象程序设计语言是基本的,但迄今为止没有统一认识。

在这个五个概念中,只有继承是面向对象的方法对程序设计语言的独特贡献。

正是由于继承与其余四个概念的相互结合,才显示出面向对象程序设计的特色。

2.1.1对象(object)

在面向对象的方法中,一切概念上的存在,小至单个整型数或字符串,大至由许多部件组成的系统均可称作对象。

对象具有主动侧面和被动侧面。

被动侧面指其相对静止侧面,由静态的属性表示,而主动侧面指把对象看作主动机制,即动态的行为。

属性决定行为,行为可以改变属性,更确切地说对象的表示应包括属性与行为,或数据与操作。

对象间可以通过通信进行交互。

对象是属性和行为(数据和操作)的封装体,其中还包括和其它对象进行通信的设施,而行为通常称作方法。

2.1.2类(class)

在面向对象的方法中,对象按照不同的性质划分为不同的类。

同类对象在数据和操作性质方面具有共性。

在面向对象程序设计语言中,程序由一个或多个类组成。

在程序运行过程中,根据需要创建类的对象(即其实例),因此类是静态概念,对象是动态概念。

类是对象之上的抽象,有了类之后,对象则是类的具体化,是类的实例。

把一组对象的共同特性加以抽象并存贮在一个类中的能力,是面向对象方法最重要的一点,是否建立了一个丰富的类库,是衡量一个面向对象程序设计语言成熟与否的重要标志。

在面向对象程序设计语言中,类的作用有二:

一是作为对象的描述机制,刻划一组对象的公共属性和行为;二是作为程序的基本单位,它是支持模块化设计的设施,并且类上的分类关系是模块划分的规范标准。

2.1.3方法(method)

方法也称作行为(behavior),指定义于某一特定类上的操作与规则。

具有同类的对象才可为该类的方法所操作,换言之,这组方法表达了该类对象的动态性质,而对于其它类的对象可能无意义,乃至非法。

规则,说明了对象的其他特征之间是怎样联系的,或者对象在什么条件下是可行的。

有时这样的规则称作不变式。

对于面向对象的研究来说,有人认为规则是一种方法,也有人认为规则是一个单独的描述。

2.1.4消息(message)

面向对象的方法对另一个对象的操作在于选择一对象并通知它要作什么。

该对象“决定”如何完成这一任务,即在其所属类的方法集合中选择合适的方法作用于其身。

形象地说,在操作完成过程中对象是主动方面,所谓“操作一个对象”并不意味着直接将某个程序作用于该对象。

而是利用传递消息,通知对象自己去执行这一操作。

接收到消息的对象经过解释,然后予以响应。

发送消息的对象不需要知道接收消息的对象如何对请求予以响应。

这一设施与多用户并发执行环境及分布式环境或多或少都有联系,因为它反映了对象主动一方的非同步控制。

2.1.5封装(encapsulation)

在面向对象的方法中,所有信息都存贮在对象中,即其数据及行为都封装在对象中。

影响对象的唯一方式是执行它所属的类的方法即执行作用于其上的操作。

这就是信息隐藏(informationhidding),也就是说将其内部结构从其环境中隐藏起来。

要是对对象的数据进行读写,必须将消息传递给相应对象,得到消息的对象调用其相应的方法对其数据进行读写。

因此可知,当使用对象时,不必知道对象的属性及行为在内部是如何表示和实现的,只须知道它提供了那些方法(操作)即可。

2.1.6继承(inheritance)

不同类之间存在相似性。

两个或更多的类经常会共享属性和/或方法。

因此我们不需要重复地编写代码,这样就需要一种机制来利用这些相似性。

继承是一种使用户得以在一个类的基础上建立新的类的技术。

新的类自动继承旧类的属性和行为特征,并可具备某些附加的特征或某些限制。

新类称作旧类的子类,旧类称作新类的超类,继承能有效地支持软件构件的重用,使得当需要在系统中增加新的特征时,所需新代码最少,并且当继承和多态、动态联编结合使用时,为修改系统所需变动的原代码最少。

继承机制的强有力之处还在于它允许程序设计人员可重用一个未必完全符合要求的类,允许对该类进行修改而不至于在该类的其它部分引起有害的副作用。

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

正因为继承机制才使得子类的对象也是超类的对象,所以所有发给超类对象的消息,子类对象也可以接收。

例如类“cycle”是类“shape”的子类,所以一个cycle对象可以接收发给shape对象的消息。

2.1.7多态(polymorphism)和重载(overloading)

在收到消息时对象要予以响应,不同的对象收到同一消息可以产生完全不同的结果,这一现象叫做多态。

多态是指能够在不同上下文中对某一事物(变量、函数或对象)赋予不同含义或用法。

多态一般分为继承多态、重载多态、模板多态。

面向对象技术中的多态多指继承多态,从这个角度讲,多态是继承的一种结果。

重载多态和模板多态是静态多态,即多态行为是在编译期决定的。

有人也将基于模板的泛型编程称为编译期编程。

而继承多态是一种动态多态的形式,即多态行为可以在运行时动态改变。

重载能够使得将多以一个的含义赋予程序中出现的一个名字上。

重载最常用在变量名上:

在大多数的程序设计语言中,不同的变量如果属于不同的模块,就有可能具有相同的名字,但是在这里我们只探讨程序重载(routineoverloading)。

类的继承与多态结合后,将进一步增强软件的重用性。

多态主要有如下内容:

1)运算符重载:

同一运算符可用于不同的变量类型,称作运算符重载。

例如,“加”运算既可用来加两个整数,也可实现浮点数相加、复数相加(由程序定义复数)、复数与整数相加或与浮点数相加...等。

在这些情况下,“同样”的操作对于不同的参数类型保持运算功能的透明性。

2)即席多态(adhocpolymorphism):

即席多态也称操作名重载。

同一操作名可作用于不同对象上并产生不同的结果。

例如“OPEN”操作既可作用于“数据流”也可作用于“窗口”等不同对象上。

这种多态很有用,但如果使用不当会产生错误结果。

因此,程序员应选择避免发生误解释的、意义明确的操作名。

3)类属软件(genericsoftware)的重用:

类的继承与多态密切相关,作用于超类实例的方法同样也可以作用于其子类的实例。

超类的方法不仅可由已存在的子类所重用,而且还可以由新创建的子类所重用。

另外,通过从超类中抽取出共性利用类继承机制实现软件重用。

类属对象类(genericobjectclass)通过对类仅作部分描述并且使参数作为一种未知的东西来实现软件重用。

这些参数通常是类属类的实例可以操纵的类的对象。

通常有两种类属对象:

一类是同类的“容器(container)”对象,例如数组及列表,可以对任何种类对象进行操作。

另一种是“工具(tool)”对象,例如排序器或编辑器,只能作用于某些种类的对象,其参数必须加以约束来指明这些参数所需要超类。

排序器仅能对有比较操作的对象进行排序,排序对象能利用“总体排序”的类属类的多态,并将操作平等地施加于满足约束的对象中。

2.1.8动态联编(dynamicbinding)

联编(binding)是把一个过程调用和响应这个调用而需要将执行的代码加以结合的过程。

联编在编译时刻进行的叫静态联编(staticbinding)。

动态联编则是在运行时(runtime)进行的,因此,一个给定的过程调用和代码的结合直到调用发生时才得以进行,因而也叫迟后联编(latebinding)。

图2.1典型的动态联编

在图2.1中,BirdController有一个属性为bird,所以BirdController只和超类Bird的对象一起工作,因为bird是Bird的对象,但是这是不知道bird到底是什么具体类的对象。

Relocate()代码可以是这样的:

relocate()

{

bird.move();

}

利用该方法,不用针对具体的类编写具体的代码,实际执行是这样的:

当bird的值是Goose对象时,relocate中的代码要和Goose中定义的move的代码联编。

如果bird的值是Bird其他子类的对象时,要与相应子类中的move的代码相联编。

这种联编是在运行时可进行的,因此是动态联编。

多态是否能影响运行时开销,决定于程序设计语言是否允许动态联编。

如果变量动态地与不同对象类的实例进行联编,必须在运行时刻检索出适当的方法(run-timemethodlookup),例如在SMALLTALK中,需要在运行时刻从类层次中进行检索,以找出继承的方法,这时动态联编的费用会很小,当然与之相伴的是当修改一个由许多子类继承的方法时,将伴随着许多工作。

在C++中,一个对象类的设计者可以决定是否允许动态联编,可以定义某些操作为虚函数,子类可以指定为虚函数的实现,在某些实例上对这些函数的调用将在运行时刻解决,这也是在这些实例所属于的类的基础上解决的。

2.2对象(object)

2.2.1简述

对象(object)一词应用广泛,难以精确定义,场合不同,含义各异。

一般说来,任何事物均看成“对象”,但对于计算机软件来说,则失之过泛。

在这里,对象指是一个实体,它能够保存一个状态(或称信息或数据),并且它能提供一系列操作(或称行为),这些操作或能检查或能影响对象的状态。

对象能够表示现实或抽象的事物,具有良好定义的责任和良好定义的行为,具有良好定义的接口。

对象通常不是太复杂或太大。

一个对象可以由多个对象组成,并且与其它对象具有松散耦合。

对象具有封装性(encapsulation)。

对象将数据及行为封装在一起,并且对象具有信息隐藏的能力,也就是说将其内部结构隐藏起来。

具体地说,外界不能直接修改对象的状态,只有通过向该对象发送消息(message)来对它施加影响。

对象隐藏了其中的数据及操作的实现方法,对外可见的只是该对象所提供的操作的接口,对象将接口从实现中分离。

但某些面向对象程序设计语言中,信息隐藏是有权限的,如C++。

通过封装,可以防止对封装数据XX的访问;有助于保证数据的完整性,隐藏起来的执行细节,对其他对象是透明的,因此内部细节的改动不影响向其发送消息的对象。

对象具有自治性(autonomy)。

对象具有独立的计算能力。

给定一定的输入,经过状态转换,对象能产生输出,说明它具有计算能力。

对象自身的状态变化不是直接受外界干预的,外界只有通过发送消息对其产生影响,因此对象能够提供服务。

对象具有通信性。

对象具有与其它对象通信的能力,具体地说就是对象能接收其它对象发来的消息,同时也向其它对象发送消息。

通信性反映了不同对象间的联系,通过这种联系,若干对象可以协同完成某项任务。

对象具有被动性。

对象的存在和状态转换都是由来自外界的某种刺激(stimulus)引发的,这种刺激就是消息。

对象的存在是由外界决定的,而对象的状态转换则是在它接收到某种消息后产生的。

在面向对象程序设计语言中,对象由若干属性值及方法组成。

对象的属性和方法称作对象的特性(property)。

属性值即对象的状态,方法即对象的行为。

属性在内部实际上是一组变量。

方法是一组函数或过程。

在smalltalk中,影响对象属性值的唯一方法是否可以直接访问对象的属性及方法。

在C++中,属性称作数据成员,方法称作成员函数。

2.2.2对象标识(objectidentifier)

对象标识是将一个对象和其它对象加以区别的标识符,这是面向对象的一个非常重要的概念。

在一个完全的面向对象系统中,一个对象标识和对象永久结合在一起,不管这个对象状态如何变化,一直到该对象消亡为止。

对象标识独立于对象的值,不管对象属性值如何改变,对象标示是不变的。

在面向对象的程序设计语言中,强调对象标识的表达能力,而在面向对象的数据库系统中则希望对象标识能够支持持久性。

面向对象数据库系统的对象标识详见面向对象数据库系统的有关章节。

区分对象有许多不同的办法。

在许多语言中,用变量名充当标识,这使得标识与对象的位置及可寻址性有关,区分两个对象实际上是它们的地址。

基于地址的对象标识在语言中一般用指针来实现。

这种方法把可寻址性和标识这两个概念做了混合。

实际上可寻址性对于对象来说是外部的特性,其目的是提供特定环境下访问对象的一条途径;标识则是对象内部特性,其目的是为对象的个体性提供一种表示,与访问对象的途径无关。

所以基于地址的标识是表示对象标识的这种方案。

使用变量作为对象标识,如果没有测试措施,则必须加以限制,因为,在程序运行期间对象大都是动态产生的,用同一个变量在不同时刻可以标识不同的对象。

由于每个对象都是每个类的实例,所以可对变量所能识别的对象种类加以限制(smalltalk无限制)借以减少程序运行期间的错误。

变量通常用下列的形式定义:

Ax,y;这里定义的两个变量x,y它们所标识的对象都是类A的实例。

变量标识对象的方式有两种,即直接标识与间接标识。

直接标识就是变量的值即为要标识的对象,间接标识指变量的值不是要标识的对象而是该对象的指针。

见下图:

 

在支持对象的模型中,对象独立于它们的值而存在,因此有两个关于对象等价的概念:

一是两个对象同一,即它们具有相同的标识;另一是相等,即两个对象的标识不同,但具有相同的值。

2.2.3复合对象

有些对象可由其它对象组成,组成的原因可以依赖于多种因素,它通常依赖于一种使对象详细化,增加易懂性的愿望,并且希望得到可重用的部分。

我们说一个对象O1引用了另外一个对象O2,意味着O1的一个属性的值是O2。

实际上,对象O1的某个属性对对象O2的引用是通过对象表示来完成的,也就是说O1中引用O2的属性的值是O2的对象标示。

复合对象(compositeobject)是指一个对象的一个属性或多个属性引用了其他对象。

有时复合对象也称作复杂对象。

换句话说,一个复合对象好像将一个对象嵌套在另一个对象里面一样。

将不同的部分联在一起的一种方法是通过使用组合。

一个对象可以由其它对象构造,这样的联系称作包含(consist-of)联系。

下图说明了组合的例子。

 

 

 

描述对象间具有相互关系的另一种方式是通过使用聚合(aggregate)。

组合层次与聚合有时当做同一词使用,但仍由一些差别。

聚合的意思是连接在一起,是划分的反义词。

例如在家庭关系中,将男人、女人和孩子组合在一起建立起一个聚合关系称作“家庭”,由于不好表达这三者之间的关系,必须增加一个对象“家庭”来表达这种聚合,但并不是聚合本身。

一个聚合是多个对象的一个并集,通常由一个对象自身来表示。

组合是更强形式的聚合。

其中整体负责部分,而每个部分对象也仅与一个整体对象联系。

例如在任何给定的时间,引擎是且仅是飞机的一部分,而且除了飞机以外,其他对象不能直接与引擎对象发生交互,例如飞机上的乘客不能直接请求引擎加速。

如何区分组合与聚合?

1、应用语义规则。

第一项测试应该是“部分是整体的一部分”这句话要有意义,例如说引擎是飞机的一部分是有意义的。

但是说雇员是职位的一部分就没有意义了。

如果语句没有意义,那么很有可能组合也不适用。

2、整体应该管理部分。

假定语句规则已经通过,第二条测试,是整体是否管理部分。

例如飞机可以管理其引擎,但是乘客不能管理引擎。

3、应该对部分发生兴趣。

对象实际上可能是现实世界的一部分,如果我们对跟踪它不感兴趣,也不会对建模发生兴趣。

例如飞机维护系统会对引擎感兴趣,因为它需要记录每个引擎的维护信息。

另一方面,空中管制系统不会对引擎感兴趣,而只会对飞机有兴趣。

在空中管制系统中,引擎不会作为类来出现。

为了能够对上述语义进行更加明确的描述,我们将探讨引用的语义。

引用语义分为两大类:

一类是描述的是否依赖,另一类描述的是是否共享。

依赖引用:

如果对象o1引用了对象o2,如果对象o1不存在了,那么对象o2也就不存在了。

独立引用:

如果对象o1引用了o2,o2的存在不取决于o1的存在。

共享引用:

对象o1引用了对象o2,同时还有其他对象也引用了o2。

派他引用:

如果对象o1引用了对象o2,那么不存在另外其他对象同时引用o2。

实际上上述两类引用语义通过组合可以生成4种引用语义:

依赖共享引用、依赖派他引用、独立共享引用、独立派他引用。

 

―――――――――――――――――先不讲

委托(delegation)是复合对象的一个特例。

在委托方式下可,有两个对象参与处理一个请求,接受请求的对象将责任委托给它的代理者。

例如在一个窗口对象保存一个矩形对象来代理矩形对象的特定操作,这样窗口可以复用矩形对象的操作,从图中可以看到,计算窗口的面积可以将责任委托给矩形。

 

2.2.4对象持久化

从开发的角度来看,有两种类型的对象:

要长久保存的对象,也就是持久对象(persistentobject)和不需要长期保存的暂存对象(transientobject)。

持久对象不随着创建它的进程结束而消亡,并且在外存中存贮。

对象的持久性可以从两个方面理解。

一个方面是应用系统急需管理的客观存在的对象,例如学生等。

我们必须把对象的属性值以及维护关系相关的任何信息都需要永久存储。

除了保存对象之外,持久化还关注对象的检索和删除。

利用面向对象的方法进行软件开发,设计的都是对象以及对象之间的关系。

但是存储的却是关系数据库,这样也就存在了对象/关系映射的问题。

我们将有专门的章节来探讨持久对象。

另一方面,在面向对象的应用中,经常需要将暂存对象(内存中的对象)转换成持久对象(在外存中存储),应用需要时,再将持久对象转换成暂存对象。

2.3类和实例

2.3.1简述

在面向对象的系统中,有许多可以互相通信的对象,有些对象具有共同的特性,于是根据这些特性将这些对象进行分类。

一个类就是这些具有相同或相似行为或数据结构的对象的共同描述,类是若干对象的模板,并且能够描述这些对象内部的构造。

属于同一个类的对象具有相同数据结构及行为。

类应至少具有以下几个性质:

(1)类的名标识一个类,虽然可以给每个类赋予一个同义词。

(2)在同一个系统环境中,类的名能够唯一标识一个类。

(3)类必须具有一个成员集合,包括数据结构(称作属性)及行为(称作方法)以及方法的操作接口。

(4)类的属性的域可以是基本类,也可以是用户定义的类,如果为后者,则称该属性为复合属性,这样的类也称作复合类。

(5)支持信息隐藏。

这是通过将类的接口及类的实现隔离而实现的,这种隔离允许将类接口映射到多个不同的实现,同时看起来外部接口的操作符表达了对象可能的行为,这种操作符的责任是提供对对象属性的有控制的访问,这样就将用户和类隔离开,这样使得对象之间具有松散耦合。

常言道只有建好围墙,才能成为好的邻居。

从类自身内容来看,它描述了一组数据及其上的操作,这些数据为类所私有,只有操作的接口对外可见,类体现了一种数据抽象,所以类是抽象数据类型在面向对象程序设计语言的具体实现。

其含义是即给出了具体的数据结构表示,又用面向对象的语言语句给出操作的实现。

其意思是既给出了具体的数据结构表示,又用面向对象的语言语句给出操作的实现。

2.3.2抽象数据类型和类

Inthesearchforagoodmodularstructurebasedonobjecttypes,abstractdatatypesprovideahigh-leveldescriptionmechanism,freeofimplementationconcerns.Theywillleadustothefundamentalstructuresofobjecttechnology.

抽象数据类型提供了高层次的的描述机制,而不考虑实现。

抽象数据类型是对象技术基础结构。

Moreprecisely,anobject-orientedsystemwillbebuilt(atthelevelofanalysis,

designorimplementation)asacollectionofinteractingADTs,partiallyortotally

implemented.

更加确切地说,一个面向对象的系统是由一个相互交互的抽象数据类型集合构成,在构成是这些ADT或者部分地得以实现或者全部得以实现。

Definition:

class

Aclassisanabstractdatatypeequippedwithapossiblypartialimplementation.

定义:

类是一个可能部分实现的抽象数据类型。

2.3.3类和型的区别

在某些文献中有一个不太清晰的概念,即类(class)和型(type)是一样的,实际上这两个概念是有差别的。

类是具有共同属性和方法的对象的集合,而对象的型(type)是类的说明,而类是型的实现。

对象型代表的是内含(intension)、而不是外延(extension)。

对象型的属性和方法通常指的是他的特征和职责。

属性表示直到某事物的职责,方法表示做某事的职责

一个型的说明是指概念上,逻辑上的问题。

数据的值都有型。

一个类指一个特定的抽象数据类型实现模板,对象具有类。

型是定义在值上的一个谓词布尔函数,而不能用在限制一个可能的参数或表征某一个结果,型通过一个公共的接口对对象进行分类。

如果一个型定义了对象是如何定义和实现的,那么将通过定义新的型来实现应用。

一个型包括:

(1)一个操作接口集合。

(2)操作的代码。

(3)定义对象表达的数据结构。

定义的对象组织成一个层次,允许一个子型继承和重用文型定义的操作。

一个类是一个能够实例化出多个具有同样行为的对象的设计部分,一个对象是一个类的实例,同类型相反,类通过一个公共的实现来区分对象。

有些人认为类和型关系密切并可以交换使用,也有一些人认为类和型完全不同,实际上,上述两种看法都是不对的:

类具有一个外部的意义,指明适合于型的对象集合。

型是一个对象集合特征的内部定义。

2.3.3类的实例

在面向对象的系统中,每个对象都属于一个类,属于某个类的对象称为该类的一个实例(instance),类和对象间具有instance-of关系。

一个实例是从一个类创建而来的对象,类描述了这个实例的行为(方法)及结构(属性)。

实例的当前状态由在该实例执行的操作来定义。

类是静态的,实例对象是动态的。

实例的行为和属性由其所在的类来定义,每个实例具有一个对象标识。

许多不同的实例可以由某一个类所创造,每个实例可由该类上定义的操作(方法)来操纵,不同的实例可以由不同的操作序列来操纵,结果是得到不同的状态。

如果这些实例严格地用同样的操作方法进行操纵,必定得到相同的状态

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1