知识点的梳理:
- 用户可以通过user_types(dba_types)及dba_source数据字典查看EMP_OBJECT的相关信息;
- 面向对象有3个主要特征:封装,继承,多态;
- 如果一个类要设置继承则必须指定NOTFINAL,否则此类无法被继承;
- 如果要对查询出来的数据进行排序,可以使用MAP或ORDER定义函数;
- 在一个类中,默认提供的构造方法需要传递全部的属性内容,如果用户有需要,也可以利用CONSTRUCTOR来定义指定参数的构造函数;
- 在面向对象中,可以通过子类为父类实例化,这样每一个父类对象所调用的函数会根据覆写此子类的不同而实现不同的功能;
- 一个类可以使用NOT INSTANTIABLE来定义抽象函数,而抽象函数所在的类被称为抽象类,抽象类继承时需要由子类使用OVERRIDING进行函数的覆写;
- 可以根据指定的类创建数据表,这样表中的字段就是类中的属性;
-
通过对象视图,可以将一张数据表中的数据直接以类对象的形式返回;
-
定义对象类型---类
-
在PL/SQL中对象类型的定义与包的定义格式非常相似,由如下两部分组成;
- 对象规范(或称为类规范):定义对象的公共操作标准,例如公共属性或子程序;
- 对象体(或称为类体):实现对象类型规范中的公共子程序;
- 类规范定义格式:
-
CREATE [OR REPLACE] TYPE 类规范名称 属性名称数据类型,....... [MAP | ORDER] MEMBER 函数名称, [FINAL | NOTFINAL] MEMBER 函数名称, [INSTANTIABLE | NOTINSTANTIABLE] MEMBER 函数名称, CONSTRUCTOR MEMBER 子程序名称,..... OVERRIDING MEMBER 子程序名称,.... [MEMBER | STATIC] 子程序名称,..... )[FINAL | NOTFINAL] |
关于此方法各个组成部分解释如下: 属性名称数据类型,......:定义类中的若干个组成属性; [MAP | ORDER] MEMBER 函数名称:定义该函数是否用于对象间的比较; [FINAL | NOTFINAL] MEMBER 函数名称:如果函数使用了FINAL定义,则表示子类实例不可以覆写这个函数,而NOTFINAL表示子类可以覆写此函数; [INSTANTIABLE | NOTINSTANTIABLE] MEMBER 函数名称:表明此函数是否可以被实例化对象调用,INSTANTIABLE表示此函数可以被实例化,可以通过对象调用,而NOTINSTANTIABLE则表示这个函数专门用于子类重载函数使用,实例化对象无法调用此函数; CONSTRUCTOR MEMBER 子程序名称,.....:定义构造方法; OVERRIDING MEMBER 子程序名称,....:定义函数覆写; [MEMBER | STATIC] 子程序名称,.....:定义函数,其中MEMBER定义的函数表示由实例化对象调用,如果是STATCI定义的函数表示由类进行调用; [FINAL | NOTFINAL]:如果使用了FINAL,则表示此类不允许有子类,NOTFINAL表示可以有子类; |
PL/SQL与JAVA面向对象的关联表:
|
- 除了定义对象规范之外,还需要针对对象规范定义实现的对象体,该语法如下:
CREATE [OR REPLACE] TYPE BODY 对象规范名称 [ IS |AS ] |
对象体的主要功能是实现对象规范中所定义的所有未实现函数的函数体。 |
-
举个栗子
-
示例1:定义类规范
-
CREATE OR REPLACE TYPE emp_object AS OBJECT ( -- 定义对象属性,与emp表对应 atri_empno NUMBER(4) , -- 雇员编号 atri_sal NUMBER(7,2) , -- 雇员工资 atri_deptno NUMBER(2) , -- 部门编号 -- 定义对象操作方法 -- 此过程的功能是根据部门编号按照一定的百分比增长部门雇员的工资 MEMBER PROCEDURE change_dept_sal_proc(p_deptno NUMBER, p_percent NUMBER) , -- 此函数的功能是取得指定雇员的工资(包括基本工资和佣金) MEMBER FUNCTION get_sal_fun(p_empno NUMBER) RETURN NUMBER ) NOT FINAL ; / |
在此类规范中,一共定义了3个属性(atri_empno,atri_sal,atri_deptno)和两个普通方法(change_dept_sal_proc,get_sal_fun),同时此规范使用了NOT FINAL,表示依然可以定义其子类 |
-
示例2:定义类体
CREATE OR REPLACE TYPE BODY emp_object AS MEMBER PROCEDURE change_dept_sal_proc(p_deptno NUMBER, p_percent NUMBER) AS BEGIN UPDATE emp SET sal=sal*(1 + p_percent) WHERE deptno=p_deptno ; END ; MEMBER FUNCTION get_sal_fun(p_empno NUMBER) RETURN NUMBER AS v_sal emp.sal%TYPE ; v_comm emp.comm%TYPE ; BEGIN SELECT sal,NVL(comm,0) INTO v_sal,v_comm FROM emp WHERE empno=p_empno ; RETURN v_sal + v_comm ; END; END ; / |
在类规范中定义了两个普通的函数,但是此函数并没有具体的函数体,所以要在类体中实现这两个函数。实现之后可以通过一个恶PL/SQL程序块使用类产生对象,并进行操作。调用方式有以下两种: |
-
示例3:声明对象并使用类
DECLARE v_emp emp_object ; BEGIN -- 实例化类对象 v_emp := emp_object(7369,800.0,20) ; -- 修改对象中atri_sal属性的内容 v_emp.atri_sal := 1000 ; -- 取得修改后的工资数额 DBMS_OUTPUT.put_line('7369雇员修改后的工资:' || v_emp.atri_sal) ; -- 通过对象调用类中的函数,取得7566雇员的工资 DBMS_OUTPUT.put_line('部门工资修改前,7566雇员的总工资:' || v_emp.get_sal_fun(7566)) ; -- 修改20部门雇员的工资,上涨30% v_emp.change_dept_sal_proc(20,0.3) ; -- 通过对象调用类中的函数,取得7566雇员的工资 DBMS_OUTPUT.put_line('部门工资修改后,7566雇员的总工资:' || v_emp.get_sal_fun(7566)) ; END ; / |
此程序实例化了emp_object对象,在实例化对象时传入了所定义的若干个参数(empno,sal,deptno),而后可以利用"对象.属性:=数值"的方式修改对对象中属性的内容,通过"对象.函数名称()"也可以调用类中的子程序; |
-
删除类型
- 语法:
DROP TYPE 类型名称; |
- 示例1:删除emp_object类
DROP TYPE emp_object ; |