📄 第十章 pl-sql对象类型 - pl-sql用户指南与参考 - whatiswhat.htm
字号:
<TABLE
style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV id=art style="MARGIN: 15px">
<CENTER><IMG alt=""
src="第十章 PL-SQL对象类型 - PL-SQL用户指南与参考 - whatiswhat.files/o_cover.jpg"><BR><IMG
alt=""
src="第十章 PL-SQL对象类型 - PL-SQL用户指南与参考 - whatiswhat.files/o_banner.gif">
</CENTER>
<DIV id=chapter>第十章 PL/SQL对象类型 </DIV><!-- InstanceEndEditable --><!-- InstanceBeginEditable name="EditRegion2" -->
<P class=title1>一、抽象的角色</P>
<P>抽象是对一个真实世界实体的高级描述或建模。它能排除掉无关的细节内容,使我们的日常生活更有条理。例如,驾驶一辆汽车时,我们是不需要知道它的发动机是如何工作的。由变速排档、方向盘、加速器和刹车组成的接口就能让我们有效地使用它。而其中每一项的详细信息对于日常驾驶来说并不重要。
</P>
<P>抽象是编程的核心内容。例如,我们在隐藏一个复杂的算法时只要编写一个过程,然后为它传递参数就可以做到过程化抽象。如果需要改变具体的实现,换一个过程体即可。有了抽象后,那些调用过程的程序就不需要再修改了。
</P>
<P>我们在指定变量的数据类型时,可以使用数据抽象。数据类型代表了对于想操作的数值的值集合和操作符集合。比如说一个POSITIVE类型的变量,只能存放正整数,也只能用于加减乘等运算。使用这个变量时,我们不必知道PL/SQL是如何存储整数或是实现算术运算的。
</P>
<P>对象类型是大多数编程语言内置类型的一个概括。PL/SQL提供了大量的标量类型和复合类型,每种类型都与一组预定义操作符相关联。标量类型(如
CHAR)是没有内部组成成分的。但复合类型(如RECORD)是有内部组成成分的,并且其中每一个部分都可以被独立操作。同RECORD类型一样,对象类型也是复合类型。但是,它的操作是用户自定义的,而不是预定义的。
</P>
<P>目前,我们还不能用PL/SQL定义对象类型。它们必须用CREATE语句创建并存放在Oracle数据库中,这样才能被许多程序所共享。使用对象类型的程序称为客户端程序,它可以声明并操作对象,但并不要求知道对象类型是如何表现数据或实现操作。这就能够让我们分别编写程序和对象类型,即便是在改变了对象实现时也不会影响到程序。因此,对象类型既支持过程化和又支持数据抽象。
</P>
<P class=title1>二、什么是对象类型</P>
<P>对象类型是一个用户自定义复合类型,它封装了数据结构和操作这个数据结构的函数和过程。数据结构中的变量称为属性,函数和过程称为方法。通常,我们认为对象(如人、车、银行账户)都是有着属性和行为的。例如一个婴儿有性别、年龄和体重这些属性,行为有吃、喝、睡等。对象类型能够让我们把这些内容抽象出来并在应用程序中使用。
</P>
<P>使用CREATE
TYPE语句创建对象类型的时候,我们实际上是创建了真实世界中某个对象的抽象模板。模板只指定了我们在程序中能用到的属性和行为。比如一个雇员有很多属性,但通常只有他的一部分信息是我们的应用程序所需要的,见下图:
</P><IMG alt=""
src="第十章 PL-SQL对象类型 - PL-SQL用户指南与参考 - whatiswhat.files/o_10-1.gif">
<P>假设我们现在需要编写一个为雇员分发奖金的程序。因为并不是雇员的所有属性都能用于解决这个问题,所以,我们只需设计一个抽象的雇员,拥有与解决问题相关的属性即可:姓名、ID号、部门、职称、工资和级别。然后,设计一些具体的操作方法,例如更改雇员的级别。
</P>
<P>下一步就是定义用于数据表现的变量(属性)和用于执行操作的子程序集(方法)。最后,我们把属性和方法封装到对象类型中去。
</P>
<P>对象的属性是公有的(对客户端程序可见)。但是,设计良好的程序是不应该直接操作这些属性的,我们应该为这些操作编写相应的方法。这样,雇员数据就能保存在一个合适的状态。
</P>
<P>在运行时,我们可以建立抽象雇员的实例(通常称为对象),然后为它的属性赋值。我们可以按照我们的需求创建任意多个实例。每个对象都有姓名、编号、职别等,如下图所示:
</P><IMG alt=""
src="第十章 PL-SQL对象类型 - PL-SQL用户指南与参考 - whatiswhat.files/o_10-2.gif">
<P class=title1>三、为什么使用对象类型</P>
<P>对象类型能把大的系统划分为多个逻辑实体,简化系统复杂度。这就使我们可以创建模块化、可维护、可重用的组件。也能让不同小组的程序员并行开发软件组件。
</P>
<P>对象类型靠封装数据的操作来把数据维护代码从SQL脚本中分离出来,并把PL/SQL块封装到方法里。使用对象方法可以避免很多在数据访问时带来的负面影响,同时,对象类型隐藏实现细节,更新细节内容时不必修改客户端程序。
</P>
<P>对象类型可以为现实数据建模。现实世界中的复杂实体和关系都可以直接映射到对象类型中。并且,对象类型还可以直接映射到面向对象语言(如Java和C++)的类中。
</P>
<P class=title1>四、对象类型的结构</P>
<P>与包相同,对象类型也有两部分:说明和体,如下图所示。说明部分是应用程序接口;它声明了数据结构(属性集合)和所需的操作(方法)。方法体部分是对已声明方法的实现。
</P><IMG alt=""
src="第十章 PL-SQL对象类型 - PL-SQL用户指南与参考 - whatiswhat.files/o_10-3.gif">
<P>客户端程序要使用到的所有方法都在说明中声明。我们可以把对象说明想象成一个可选的接口,把对象体想象成一个黒盒。我们可以在不改变说明部分的前提下调试,增强或替换对象体,并且不会对客户端程序造成影响。
</P>
<P>在一个对象说明中,所有的属性都必须声明在方法之前。只有子程序的声明才需要实现。所以,如果一个对象类型的说明只声明了属性,那么对象类型的体就没有必要了。我们不能在对象体中声明属性。对象说明中的声明都是公有的。
</P>
<P>为了能更好的了解结构,请看下面的例子。这是一个复数的对象类型,有实数部分和虚数部分,并有几个与复数操作相关的方法。
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>CREATE</STRONG> <STRONG>TYPE</STRONG> complex <STRONG>AS</STRONG> OBJECT(<BR> rpart <STRONG>REAL</STRONG>, <EM>-- attribute</EM><BR> ipart <STRONG>REAL</STRONG>,<BR> MEMBER <STRONG>FUNCTION</STRONG> plus(x complex)<BR> <STRONG>RETURN</STRONG> complex, <EM>-- method</EM><BR> MEMBER <STRONG>FUNCTION</STRONG> LESS(x complex)<BR> <STRONG>RETURN</STRONG> complex,<BR> MEMBER <STRONG>FUNCTION</STRONG> times(x complex)<BR> <STRONG>RETURN</STRONG> complex,<BR> MEMBER <STRONG>FUNCTION</STRONG> divby(x complex)<BR> <STRONG>RETURN</STRONG> complex<BR>);<BR><BR><STRONG>CREATE</STRONG> <STRONG>TYPE</STRONG> <STRONG>BODY</STRONG> complex <STRONG>AS</STRONG><BR><BR> MEMBER <STRONG>FUNCTION</STRONG> plus(x complex)<BR> <STRONG>RETURN</STRONG> complex <STRONG>IS</STRONG><BR> <STRONG>BEGIN</STRONG><BR> <STRONG>RETURN</STRONG> complex(rpart + x.rpart, ipart + x.ipart);<BR> <STRONG>END</STRONG> plus;<BR><BR> MEMBER <STRONG>FUNCTION</STRONG> LESS(x complex)<BR> <STRONG>RETURN</STRONG> complex <STRONG>IS</STRONG><BR> <STRONG>BEGIN</STRONG><BR> <STRONG>RETURN</STRONG> complex(rpart - x.rpart, ipart - x.ipart);<BR> <STRONG>END</STRONG> LESS;<BR><BR> MEMBER <STRONG>FUNCTION</STRONG> times(x complex)<BR> <STRONG>RETURN</STRONG> complex <STRONG>IS</STRONG><BR> <STRONG>BEGIN</STRONG><BR> <STRONG>RETURN</STRONG> complex(rpart * x.rpart - ipart * x.ipart,<BR> rpart * x.ipart + ipart * x.rpart);<BR> <STRONG>END</STRONG> times;<BR><BR> MEMBER <STRONG>FUNCTION</STRONG> divby(x complex)<BR> <STRONG>RETURN</STRONG> complex <STRONG>IS</STRONG><BR> z <STRONG>REAL</STRONG> := x.rpart ** 2 + x.ipart ** 2;<BR> <STRONG>BEGIN</STRONG><BR> <STRONG>RETURN</STRONG> complex((rpart * x.rpart + ipart * x.ipart) / z,<BR> (ipart * x.rpart - rpart * x.ipart) / z);<BR> <STRONG>END</STRONG> divby;<BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P class=title1>五、对象类型组件</P>
<P>对象类型封装了数据和操作。我们可以在对象类型说明中声明属性和方法,但不能声明常量、异常、游标或类型。我们至少要声明一个属性(最多1000个),方法是可选的。
</P>
<P class=title2>1、属性</P>
<P>同变量一样,属性也有名称和数据类型。对象类型中的名称必须是唯一的(但在其他的对象类型中可以重用)。除了下面几种类型之外,其他任何Oralce类型都可以使用:
</P>
<OL>
<LI>LONG和LONG RAW
<LI>ROWID和UROWID
<LI>PL/SQL特定类型BINARY_INTEGER及它的子类型、BOOLEAN、PLS_INTEGER、RECORD、REF
CURSOR、%TYPE和%ROWTYPE
<LI>PL/SQL包内定义的数据类型 </LI></OL>
<P>我们不能在声明属性的时候用赋值语句或DEFAULT子句为它初始化。同样,也不能对属性应用NOT
NULL约束。但是,对象是可以存放到添加了约束的数据表中。 </P>
<P>数据结构中的属性集合依赖于真实世界中的对象。例如,为了表现一个分数,我们只需要两个INTEGER类型的变量。另一方面,要是表现一个学生,我们需要几个VARCHAR2来存放姓名、住址、电话号码和状态等,再添加一个VARRAY类型变量用来存储课程和分数。
</P>
<P>数据结构可能是复杂的。例如,一个属性的数据类型可能是另外一个对象类型(称为嵌套对象类型)。有些对象类型,像队列、链表和树,都是动态的,它们是随着使用的需要而动态改变存储长度的。递归对象类型能够直接或间接的包含自身类型,这样就能创建出更诡异的数据类型。
</P>
<P class=title2>2、方法</P>
<P>一般的,方法就是用关键字MEMBER或STATIC声明在对象说明部分的子程序。方法名不能和对象类型名、属性名重复。MEMBER方法只能通过对象实例调用,如:
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD noWrap>instance_expression.method()
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>但是,STATIC方法直接通过对象类型调用,而不是实例,如:</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -