复旦大学 楼荣生 罗文化
面向对象(object-oriented,OO)数据模型与传统数据模型比较至少在下列各方面具有优
势:
·表示复杂对象的能力;
·由封装和信息隐藏概念提供的模块化机制;
·通过封装和继承概念提供的软件重用机制;
·通过滞后联编等概念得到的系统扩充能力。
因此,该模型受到学术界和工程界的极大兴趣。十多年来,各种OO程序设计语言(OOP)
相继问世。而在数据库界,为满足新的应用需求,开展了以OO模型为数据模型的数据库系统
(OODB)的研究工作。OODB现已成为很有前途的新一代数据库的研究方向,理论基础的研究工
作也在积极展开。经过一些年的争论,已在一系列基础概念上达到了基本一致的认识。本文
目的是介绍这些基础概念,希望能引起读者的研究兴趣。
一、对象、界面、封装
面向对象模型把客观世界模拟成为由各个相互作用的,称为对象(object)的单元组成的
复杂系统。系统中所有对象的状态共同构成系统的状态。对象状态从一个初始状态出发,在
相互作用过程中不断改变。
对象的相互作用通过一个对象向另一个对象发出某种操作请求(request)而体现。传统
对象模型把请求表示为三个组成部分:一个请求接收对象、一个操作和若干个作为操作参数
的其它对象。
一个请求执行完毕常常要向请求者返回某种形式的回答,称为回答消息。请求的接收对
象在执行操作过程中也可向其它对象发请求。
例1.图1中用矩形表示对象。银行的存款系统由众多的客户对象组成。每一客户对象有
一存款额。若要对象A划一笔款项Q给对象B,则发形如A.划款(Q,B)的请求,A是接收者。A收
到此请求后先检查自己的存款额是否小于Q,若小于Q则返回"不能划"的回答消息,操作执行
结束。否则执行划款:从自己的存款额中减去Q,再发出形如B.存款(Q)的请求。A收到B的"存
款完成"回答后再向请求者发一个"划款完成"回答。图1是划款过程的流程。
@@31S09910.GIF;图1 划款操作执行流程。@@
对象作为接收者可以执行的全部操作称为对象的界面(interface),描述了对象的行为
特征。但界面中只说明了这些操作的定义,没有规定实现方法。界面是对象提供给外界的唯
一可见部分。外界不能直接感知对象状态,只能通过执行界面上的操作和读取返回值间接进
行测试或施加影响。这种性质称为封装性(encapsulation),使对象的内外部隔离。实现了
对象的内部细节对应用程序隐藏的目的。藉此把大系统分解为封闭在对象内部的小系统。
封装是对象模型的关键性概念之一。
对象状态可以影响请求的执行结果。是隐藏在对象内部的信息,如例1中的客户对象的
存款额。状态表示为一系列属性的值,这些值可是如数字、词等直接量,也可以是其它对象
。属性值都是直接量的对象是简单对象;有其它对象作属性值的对象是复合对象。这样,复
合对象是一个层次结构,是对象概念不同于关系模型中元组的重要特征,也是物理实现的难
点之一。
综上所述,一个对象的定义包括状态和行为(界面)两个方面。状态由一组属性值组成,
行为由一组操作组成。只有通过向对象发消息调用界面中的这些操作才能查询和修改属性
值。
二、对象类、方法、多态
对象按实现的共性分组称为对象类(class),所谓实现是指组成对象界面的操作的实现
程序。这样,同一类对象所有操作的实现相同。这里强调的是操作的实现(或称方法,metho
d),而不是定义。操作的定义在界面中,只规定了操作名、返回值类型、参数的个数和类型
,以及可能还有的语义描述,不涉及实现方法。把实现方法与定义分离提供了极大的灵活性
,程序员甚至可能用不同的语言实现不同的操作,并可处理各种不同媒体的信息。
如果按界面对对象分类,则得到的是更粗的分类,称为类型(type)。但在大多数场合这
两个词常常不作区分。
对象模型中允许同一操作有多个实现并存,称为多态(polymophism)。一具体对象使用
什么方法实现要有一定选择法则。多态的对象类中若按选用的方法作第二次分类,所得到的
类是原来的类的一个划分,其中每一个类是原来类的子类(subclass),原类即称为这些子类
的超类(super-class)。
引进子类概念的另一原因是处理操作和属性的共享。因为上述把对象分类的方法还有
相当的任意性,设两个对象就全部属性来说分属于两个类A和B,但它们有一部分操作的实现
相同,则又可同属于一个类C。这时从集合论观点看A和B是C的子集,C是A、B的超集。在OO模
型中因而称A和B是C的子类,C是A、B的超类。
三、继承、操作重载、滞后联编
为了定义简单,在OO模型中定义子类时只定义不同于超类的那些属性和操作,并规定超
类的属性和操作子类对象也可使用,称为子类对超类的继承(inheritance)。
子类对操作的继承一般是指实现,但也允许只继承操作的定义,然后子类自己实现该操
作。后者在OOP中很重要,称为操作重载(overloading)。问题是超类和子类常常不在一起编
译。如超类是系统程序的一个组成部分而子类在应用程序中。因而在超类编译时无法对操
作名作解释(对应到一个程序地址),而把此项工作延迟到应用程序运行时进行,这种延迟称
为滞后联编(late binding)。滞后联编是实现操作重载和多态的关键,使OO模型的扩充更灵
活。
OODB系统有单继承和多继承之分。如果每个类至多只允许有一个超类(不计超类的超类
等间接超类)的称为单继承系统,超类数可多于一个则为多继承系统。单继承系统中所有类
的继承关系图呈树形,每一结点至多只有一个父结点。而多继承的继承关系图是有向无环图
。这些图称为系统的类层次图。
例2.作为计算机文件属性的有文件名,字节数,建立或最近修改日期等,公共操作有显示
状态,修改等。所有文件于是就组成一个类。以显示状态和修改两个操作为界面。显示状态
操作查看文件的各属性值,修改操作间接地改变文件的字节数和最后修改日期这些属性值。
按照(1)的格式,这两个操作定义为
字符串 文件名.显示状态(),和
整数 文件名.修改()的形式。后面的空括号表示无参数,修改操作的返回值用以告诉请
求者本次修改操作是成功或是失败。
文件又可进一步分为可打印文件,可执行文件等等。要分出这两类文件,在文件对象类
中增加打印和执行两个操作。并在文件类中分出两个子类,如图2。其中的双继承文件类中
文件既可打印也可执行,此类有两个超类,具有所有四个操作。只有可打印文件才有打印操
作,只有可执行文件才有执行操作,这两个操作都只能各属于相应的子类。相反,根据继承性
规定,文件名、字节数和修改日期是三类对象都有的属性,显示状态和修改则是三个类都有
的操作。
@@31S09911.GIF;图2. 超类和子类@@
四、永久化、对象标识
在大多数程序设计语言中,认为对象是临时的,将随着建立它们的进程终止而消失。相
反在数据库中,对象在被删除前是永久地存在的。如果用一种OOP加数据库操作形成OODB语
言,这样在OODB系统中对象有临时和永久之分。例如,可把永久对象的生命期划分为:生成→
入库→删除(从库中)→撤销四个阶段。生成后到入库前是临时对象,入库后删除前是永久的
,可延续任意长时间。这中间程序可能运行结束,下一次再运行时又可调出使用。以后若从
库中删除该对象,内存中尚未撤销前则又是临时对象,直到从内存中撤销而永远消失。如果
对象从未入库,则生成的撤销于同一进程,这种对象只能是临时的。
内存对象的管理和永久对象管理存在着许多差别。所以在OODB中又引进许多原来的OO
概念中不存在的新概念。如对象标识(OID),内存对象库等。
OOP中对象完全局限于应用程序,应用程序结束,全部对象撤销;内存则被另一应用程序
的对象所占据。而数据库则可被看成是从古到今的应用程序史,服务于所有应用程序。因此
,其中的对象较单个应用程序多得多。如果说单个应用程序中对象的引用只要通过变量就足
够了,则在数据库中不可能定义如此多的变量,对象标识设施就由此而生。给每一对象对应
一个在整个系统内不和其它对象重复的引用代号,称为对象标识,在概念上独立于状态和行
为,对象生成时即由系统赋与,在整个生存期内不变。用户可以查看,或用以作查询,但不能
改变其值。
五、并发控制、一致性、事务
一般数据库系统的并发控制和事务概念也适用于OODB。在传统的数据库系统中,事务可
定义是把数据库从一个一致性状态变到另一一致性状态的最小操作组合,最小的含义是,这
些操作应全部完成才能保证数据库达到一个新的一致状态,如果有一个因故不能完成,则数
据库可能不一致,为维护一致性,其它已完成的操作也要撤销,即要把数据库恢复到它们执行
前的状态,这就是事务的原子性。如例1中的银行客户间的划款。若对象B因故不能完成存款
操作,则A的扣款操作应予恢复。这是事务并发控制机制的基本要求之一。
所谓一致性是指满足一致性约束。数据库的一致性约束也称完整性约束,是数据库中数
据永远要满足的一组必要条件,是数据库定义的组成部分。现有的关系数据库(RDB)系统只
支持由系统规定的少数几个约束规则。而在OODB中,由于对象的封装性,一致性约束有可能
由用户在对象类或操作中定义,并在对象生成和修改时动态检查。
处理事务间的并发关系是事务管理的另一任务。并发控制,或称调度,是为了保证事务
平行执行的正确性。有多种处理方法,封锁法是传统的做法。规则是:在一事务读数据前先
对这数据作读封锁,改数据前作写封锁,直到事务完成才释放它所作的所有封锁。读操作只
能对没有写封锁的数据进行,写操作只能对无封锁(不论读或写)的数据进行,否则称为冲突
事务,后来者进入等待队列,直到要读写的数的封锁被释放。
在对象模型中自然地以对象为单位划分事务和差别冲突。这样就把RDB中的小事务合并
成了大事务,加长了事务执行时间,增加了冲突发生的概率。
大对象的事务可能需要很长的执行时间,对这些长事务不宜用封锁法调度。故在OODB中
考虑如时标法,确认法等非封锁型的调度方法。 确认法的特点是封锁时间短,适宜长事务
调度。重做可根据第一次执行的记录由机器自动完成,若事务中有操作员的动作也不必重新
操作,故即使是长事务在重做时也成了短事务。
六、OODB语言、持久性语言、阻抗失配
OODB的另一个与传统数据库有重大区别的特征是数据库语言。OO模型的有关对象的基
本概念来自OOP,故从OOP出发开发OODB语言是省力的选择。但OODB语言不同于OOP,它是对数
据库操作的语言,要提供对数据库的操作功能。如果允许永久对象和临时对象共存,则须针
对两类不同对象,相应有内存操作和辅存操作两类,形成了所谓持久性程序设计语言。但在
查询功能方面一般OOP大为逊色。这是因为OOP用变量引用对象的方式不能对对象进行统一
管理,如设图书作为类,作者是属性。一般的OOP可从每一书对象找到它的所有作者。但不支
持另一方向的查询,即从作者查询他的所有作品,除非把作者也定义成一个类而把作品设置
成属性。但这样的的设计将在数据库中造成冗余。为此就有必要扩充OOP的查询功能。
数据模型从网状到关系的进步使数据查询语言从用户导航式的过程性语言进入到了由
系统自选查询路径的非过程性语言。但是非过程性语言的面向集合的操作方式又与通常高
级程序设计语言的面向单个数据的操作方式之间产生了不协调现象,俗称阻抗失配。阻抗失
配根本原因在于数据库的数据模型和程序设计语言不一致,因而对所有嵌入式数据库语言来
说是不可避免的。但OODB不同,它的数据模型的概念来自OOP,因此作为某一OOP的扩充的OO
DB语言,从根本上解决了阻抗失配问题。
OODB语言可以期望走得更远。藉助于它的计算完备性,可以在查询语言中进一步实现迭
代、递归等功能。
七、结语
本文阐述了面向对象数据库中的对象、封装、类和类型、继承、操作重载、滞后联编
、对象标识、永久化等概念,并对并发控制、数据库语言、一致性等概念与RDB的相应概念
作了比较。这些概念基本上覆盖了美国ANSI所属数据库系统研究组下成立的面向对象数据
库任务组发表的OODB最终报告第三章(对象数据管理参考模型)中所列概念。限于作者所见
尚浅,难免有不妥之处,望资深专家指正。
(计算机世界报 1995年 第31期)
jwebee
我的个人网站
posted on 2007-01-01 15:05
周行 阅读(531)
评论(0) 编辑 收藏 所属分类:
技术