视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
面向对象的概念
2025-09-29 04:05:08 责编:小OO
文档
 1.面向对象的概念 

    面向对象(Object-Oriented)=对象(Object)+类(Class)+ 继承(Inheritance)+通信(Communication) 

如果一个软件系统是使用这样4个概念设计和实现的,则将该软件系统称为面向对象的。下面给出每个概念的具体定义。 

1.1 对象 

从一般意义上讲,对象是现实世界中一个实际存在事物,它可以是有形的(比如一辆汽车),也可以是无形(比如一项计划)。对象构成世界的一个单位,它具有自己的静态特征和动态特征。静态特征即可用某种数据来描述的特征,动态特征即对象所表现的行为或对象所具有的功能。 

现实世界中的任何事物都可以称作对象,它是大量的、无处不在的。不过,人们在开发一个系统时,通常只是在一定的范围(问题域)内考虑和认识与系统目标有关的事物,并用系统中的对象抽象地表示它们。所以面向对象方法在提到“对象”这个术语时,既可能泛指现实世界中的某些事物,也可能专指它们在系统中的抽象表示,即系统中的对象。我们主要对后一种情况讨论对象的概念,其定义是:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务构成。 

属性和服务,是构成对象的两个主要因素,其定义是:属性是用来描述对象静态特征的一个数据项。服务是用来描述对象动态特征(行为)的一个操作序列。 

一个对象可以有多项属性和多项服务。一个对象的属性和服务被结合成一个整体,对象的属性值只能由这个对象的服务存取。 

在有些文献中把对象标识(OID)列为对象的另一要素。对象标识也就是对象的名字,有“外部标识”和“内部标识”之分。前者供对象的定义者或使用者用,后者为系统内部惟一的识别对象。(怎么感觉这点跟android开发里面的id是一样的,在某个文件下有编程人员定义的所有属性的id,并且是唯一的,一般不允许更改,属于系统内部分配。) 

另外需要说明以下两点:第一点是,对象只描述客观事物本质的与系统目标有关的特征,而不考虑那些非本质的与系统目标无关的特征。这就是说,对象是对事物的抽象描述。第二点是,对象是属性和服务的结合体。二者是不可分的。而且对象的属性值只能由这个对象的服务来读取和修改,这就是后文将讲述的封装概念。 

根据以上两点,也可以给出如下对象定义:对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用,它是一组属性和有权对这些属性进行操作的一组服务的封装体。 

系统中的一个对象,在软件生命周期的各个阶段可能有不同的表示形式。例如,在分析与设计阶段是用某种OOD/OOA方法所提供的表示法给出比较粗略的定义,而在编程阶段则要用一种OOPL写出详细而确切的源程序代码。这就是说,系统中的对象要经历若干演化阶段,其表现形式各异,但在概念上是一致的,即都是问题域中某一事物的抽象表示。 

1.2 类 

把众多的事物归纳划分成一些类是人类在认识客观世界时经常采用的思维方法。分类所依据的原则是抽象,即:忽略事物的非本质特征,只注意那些与当前目标有关的本质特征,从而找出事物的共性,把具有共同性质的事物划分为一类,得出一个抽象的概念。例如:马、树木、石头等等都是一些抽象概念,它们是一些具有共同特征的事物的集合,被称作类。类的概念使我们能对属于该类的全部个体事物进行统一的描述。例如:“树具有树根、树干、树枝和树叶,它能进行光合作用”,这个描述适合所有的树,从而不必对每棵具体的树进行一次这样的描述。 

在OO方法中,类的定义是:类是具有相同属性和服务的一组对象的集合,它为属于该类的全部对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。 

在面向对象的编程语言中,类是一个的程序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。类的作用是定义对象。比如,程序中给出一个类的说明,然后以静态声明或动态创建等方式定义它的对象实例。 

类与对象的关系如同一个模具与用这个模具铸造出来的铸件之间的关系。类给出了属于该类的全部对象的抽象定义,而对象则是符合这种定义的一个实体。所以,一个对象又称作类的一个实例(instance),而有的文献又把类称作对象的模板(template)。所谓“实体”、“实例”意味着什么呢?最现实的一件事是:在程序中,每个对象需要有自己的存储空间,以保存它们自己的属性值。我们说同类对象具有相同的属性与服务,是指它们的定义形式相同,而不是说每个对象的属性值都相同。 

读者可以对照非OO语言中的类型(type)与变量(variable)之间的关系来理解类和对象,二者十分相似,都是集合与成员、抽象描述与具体实例的关系。多数情况下,类型用于定义数据,类用于定义对象。有些面向对象的编程语言,既有类的概念也有类型概念。比如在C++中,用类定义对象,用类型定义对象的成员变量。但是也有少数面向对象编程语言(例如Object Pascal)不采用类的概念,对象和普通数据都是用类型定义的。 

事物(对象)既具有共同性,也具有特殊性。运用抽象的原则舍弃对象的特殊性,抽取其共同性,则得到一个适应一批对象的类。如果在这个类的范围内考虑定义这个类时舍弃的某些特殊性,则在这个类中只有一部分对象具有这些特殊性,而这些对象彼此是共同的,于是得到一个新的类。它是前一个类的子集,称作前一个类的特殊类。而前一个类称作这个新类的一般类,这是从一般类发现特殊类,也可以从特殊到一般。考虑若干类所具有的彼此共同的特征,舍弃它们彼此不同的特殊性,则得到这些类的一般类。 

一般类和特殊类是相对而言的,它们之间是一种真包含的关系(即特殊类是一般类的一个真子集)。如果两个类之间没有这种关系,就谈不上一般和特殊。特殊类具有它的一般类的全部特征,同时又具有一些只适应于本类对象的独特特征。 

在OO方法中关于一般类与特殊类的定义是:如果类A具有类B的全部属性和全部服务,而且具有自己特有的某些属性或服务,则A叫做B的特殊类,B叫做A的一般类。这个定义也可用另一种方式给出。如果类A的全部对象都是类B的对象,而且类B中存在不属于类A的对象,则A是B的特殊类,B是A的一般类。 

以上两个定义是等价的,但从软件开发的角度看,前一个定义运用起来将更加方便。 

考虑轮船、客轮这两个类,轮船具有吨位、时速、吃水线等属性并具有行驶、停泊等服务;客轮具有轮船的全部属性与服务,又有自己的特殊属性(如载客量)和服务(如供餐)。所以客轮是轮船的特殊类,轮船是客轮的一般类。 与一般类/特殊类等价的其他术语有超类/子类、基类/派生类、祖先类/后裔类等。 

1.3 封 装 

封装是面向对象方法的一个重要原则,它有两个涵义。第一个涵义是,把对象的全部属性和全部服务结合在一起,形成一个不可分割的单位(即对象);第二个涵义也称作“信息隐蔽”,即尽可能隐蔽对象的内部细节,对外形成一个边界(或者说形成一道屏障),只保留有限的对外接口使之与外部发生联系。这主要是指对象的外部不能直接地存取对象的属性,只能通过几个允许外部使用的服务与对象发生联系。用比较简练的语言给出封装的定义就是:封装就是把对象的属性和服务结合成一个系统单位,并尽可能隐蔽对象的内部细节。 

用“售报亭”对象描述现实中的一个售报亭,它的属性是亭内的各种报刊(其名称、定价)和钱箱(总金额),它有两个服务——报刊零售和款货清点。 

封装意味着,这些属性和服务结合成一个不可分的整体——售报亭对象。它对外有一道边界,即亭子的隔板,并留一个接口,即售报窗口,这里提供报刊零售服务。顾客只能从这个窗口要求提供服务,而不能自己伸手到亭内拿报纸和找零钱。款货清点是一个内部服务,不向顾客开放。 

封装的原则具有很重要的意义,对象的属性和服务紧密结合反映了这样一个基本事实:事物的静态特征和动态特征是事物不可分割的两个侧面,系统中把对象看成它的属性和服务的结合体,就使对象能够集中而完整地描述并对应一个具体的事物。以往有些方法把数据和功能分离开进行处理,很难具有这种对应性。封装的信息隐蔽作用反映了事物的相对性。当我们站在对象以外的角度观察一个对象时,只需要注意它对外呈现什么行为(做什么),而不必关心它的内部细节(怎么做)。规定了它的职责之后,就不应该随意从外部插手去改动它的内部信息或干预它的工作。封装的原则在软件上的反映是要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效地避免了外部错误对它的“交叉感染”,使软件错误能够局部化,因而大大减少了查错和排错的难度(在售报亭的例子中如果没有一道围板,行人的一个错误可能使报刊或钱箱不翼而飞)。另一方面,当对象的内部需要修改时,由于它只通过少量的服务接口对外提供服务,因此大大减少了内部的修改对外部影响,即减小了修改引起的“波动效应”。 

封装是面向对象方法的一个原则,也是面向对象技术必须提供的一种机制。例如在面向对象语言中,要

求把属性和服务结合起来定义成一个程序单位,并通过编译系统保证对象的外部不能直接存取对象的属性或调用它的内部服务。这种机制就叫作封装机制。 

与封装密切相关的一个术语是可见性,它是指对象的属性和服务允许对象外部存取和引用的程度。我们已经讨论了封装的好处,然而封装也有它的副作用。如果强调严格的封装,则对象的任何属性都不允许外部直接存取,因此就要增加许多没有其他意义,只负责读或写的服务。这为编程工作增加了负担,增加了运行开销,并且使程序显得臃肿。为了避免这点,语言往往采取一种比较现实的灵活态度——允许对象有不同程度的可见性。 

可见性的代价是放弃封装所带来的好处。各种语言采取了不同的作法。纯OO的编程语言一般采取严格的封装(如smalltalk);混合型OO编程语言有的完全可见(如object pascal 和 Objective-C);有的采取折中方案,即允许程序员指定哪些属性和服务是可见的,哪些是不可见的(如C++)。目前看来,折中的作法最受用户欢迎。 

1.4 继 承 

继承是OO方法中的一个十分重要的概念,并且是OO技术可提高软件开发效率的重要原因之一,其定义是: 

特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。继承意味着“自动地拥有”,或曰“隐含地复制”。就是说,特殊类中不必重新定义已在它的一般类中定义过的属性或服务,而它却自动地、隐含地拥有其一般类的所有属性与服务。OO方法的这种特性称作对象的继承性。从一般类和特殊类的定义可以看到,后者对前者的继承逻辑上是必然的。继承的实现则是通过OO系统(例如OOPL)的继承机制来保证的。 

一个特殊类即有自己新定义的属性和服务,又有从它的一般类中继承下来的属性与服务。继承来的属性和服务,尽管是隐式的(不用书写出来),但是无论在感念上还是在实际效果上,都确确实实地是这个类的属性和服务。当这个特殊类又被它更下层的特殊类继承时,它继承来的和自己定义的属性和服务又都一起被更下层的类继承下去。也就是说,继承关系是传递的。 

继承具有重要的实际意义,它简化了人们对事物的认识和描述,比如我们认识了轮船的特征之后,在考虑客轮时只要我们知道客轮也是一种轮船这个事实,那就认为它理所当然的具有轮船的全部一般特征,只需要把精力用于发现和描述客轮独有的那些特征。在软件开发过程,在定义特殊类时,不需把它的一般类已经定义过的属性和服务重复地书写一遍,只需要声明它是某个类的特殊类,并定义它自己的特殊属性与服务。无疑这将明显地减轻开发工作的强度。 

继承对于软件复用是很有益的。在开发一个系统时,使特殊类继承一般类,这本身就是软件复用,然而其复用意义不仅如此,如果把用OO方法开发的类作为可复用构件提交到构件库,那么在开发新系统时不仅可以直接地复用这个类,还可以把它作为一般类,通过继承而实现复用,从而大大扩展了复用范围。 

一个类可以是多个一般类的特殊类,它从多个一般类中继承了属性与服务,这种继承模式叫多继承。 

这种情况是常常可以遇到的。例如我们有了轮船和客运工具两个一般类。在考虑客轮这个类时就可以发现,客轮既是一种轮船,又是一种客运工具。所以它可以同时作为轮船和客运工具这两个类的特殊类。在开发这个类时,如果能让它同时继承轮船和客运工具这两个类的属性与服务,则需要为它新增加的属性和服务就更少了。这无疑将进一步提高开发效率。但在实现时能不能做到这一点却取决于编程语言是否支持多继承。继承是任何一种OOPL必须具备的功能,多继承则未必,现在有许多OOPL只能支持单继承而不能支持多继承。 

多继承无论从概念上还是从技术上都是单继承的推广。用集合论的术语解释多继承结构,即具有多个一般类的特殊类是它各个一般类交集的一个子集(可能是真子集,也可能等于这个交集)。多继承模式在现实中是很常见的,但系统开发是否采用多继承受到OOPL功能的影响。目前比较现实的作法是,在OOA阶段如实地用多继承结构描述问题域中的多继承现象,从而使系统模型与问题域具有良好的对应。在考虑实现时,如果决定选用一种仅支持单继承的语言,则把多继承转化为单继承。 

与多继承相关的一个问题是“命名冲突”问题。所谓命名冲突是指当一个特殊类继承了多个一般类时,如果这些一般类中的属性或服务有彼此同名的现象,则当特殊类中引用这样的属性名或者服务名时,系统无法判定它的语义到底是指哪个一般类中的属性和服务。解决的办法有两种,一是不允许多继承结构中的各个一般类的属性及服务取相同的名字,这会为开发者带来一些不便。二是由OOPL提供一种更名机制,使程序可以在特殊类中更换从各个一般类继承来的属性或服务的名字。

1.5 多态性 

对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现不同的行为。这使得同一个属性或服务名在一般类及其各个特殊类中具有不同的语义。 

如果一种OOPL能支持对象的多态性,则可为开发者带来不少方便。例如,在一般类“几何图形”中定义了一个服务“绘图”,但并不确定执行时到底画一个什么图形。特殊类“椭圆”和“多边形”都继承了几何图形类的绘图服务,但其功能却不同:一个是画出一个椭圆,一个是画出一个多边形。进而,在多边形类更下层的一般类“矩形”中绘图服务又可以采用一个比画一般的多边形更高效的算法来画一个矩形。这样,当系统的其余部分请求画出任何一种几何图形时,消息中给出的服务名同样都是“绘图”(因而消息的书写方式可以统一),而椭圆、多边形、矩形等类的对象接收到这个消息时却各自执行不同的绘图算法。 

有些评论者没有把多态性列入OO方法的基本特征或列入OOPL的必备功能,而是看作一种比较高级的功能。多态性的实现,需要OOPL提供相应的支持,在几种目前最实用的OOPL中仅有一部分是支持对象多态性的。与多态性的实现有关的语言功能有:重载(overload)——在特殊类中对继承来的属性或服务进行重新定义,动态绑定(dynamic binding)——在运行时根据对象接收的消息动态地确定要连接哪一段服务代码,类属(generic)——服务参量的类型可以是参数化的。下载本文

显示全文
专题