Oracle12C--操作类中的其他结构(65)
来源:互联网 发布:杭州贰贰网络 编辑:程序博客网 时间:2024/06/07 23:37
- 定义函数
- PL/SQL定义的类中,函数的定义有两种方式;
- MEMBER型函数:该函数需要通过对象进行定义,使用MEMBER定义的函数可以利用SELF关键字访问类中的属性内容;
- STATIC型函数:该函数独立于类之外,可以直接通过类名称进行调用,使用STATIC定义的函数无法访问类中的属性;
- 说明:SELF与JAVA中的this关键字具有一样的效果;
- 对比STATIC与MEMBER函数定义的区别
- 示例1:使用两种不同的方式来定义函数
CREATE OR REPLACE TYPE emp_object AS OBJECT(
atri_empno NUMBER(4) ,-- 雇员编号
--修改当前雇员编号的工资,使用类中的empno和sal属性
MEMBER PROCEDURE change_emp_sal_proc(p_sal NUMBER) ,
--取得当前雇员的工资
MEMBER FUNCTION get_emp_sal_fun RETURN NUMBER ,
--修改指定部门的全体雇员工资
STATIC PROCEDURE change_dept_sal_proc(p_deptno NUMBER , p_sal NUMBER) ,
--取得此部门的工资总和
STATIC FUNCTION get_dept_sal_sum_fun(p_deptno NUMBER) RETURN NUMBER
) NOT FINAL ;
/
本程序分别定义了两组子程序,一组采用MEMBER定义,另外一组采用STATIC进行定义;
- 接上例:定义类体实现类规范
CREATE OR REPLACE TYPE BODY emp_object AS
MEMBER PROCEDURE change_emp_sal_proc(p_sal NUMBER) AS
BEGIN
--使用SELF.atri_empno找到本类中的属性,即:更新当前对象中雇员工资
UPDATE emp SET sal=p_sal WHERE empno=SELF.atri_empno ;
END ;
MEMBER FUNCTION get_emp_sal_fun 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=SELF.atri_empno ;
RETURN v_sal + v_comm ;
END ;
STATIC PROCEDURE change_dept_sal_proc(p_deptno NUMBER , p_sal NUMBER) AS
BEGIN
--更新指定部门全部雇员的工资
UPDATE emp SET sal=p_sal WHERE deptno=p_deptno ;
END ;
STATIC FUNCTION get_dept_sal_sum_fun(p_deptno NUMBER) RETURN NUMBER AS
v_sum NUMBER ;
BEGIN
--查询指定部门的工资总和
SELECT SUM(sal) INTO v_sum FROM emp WHERE deptno=p_deptno ;
RETURN v_sum ;
END ;
END ;
/
此时类体中已经实现了类规范所定义的子程序,可以发现在MEMBER函数中可以利用"SELF.属性"的方式取得本对象中的属性内容(保存在类规范之中),而在STATIC函数中无法使用属性
- 接上例:编写PL/SQL块实例化类对象
DECLARE
v_emp emp_object ;
BEGIN
v_emp := emp_object(7369) ; --实例化emp_object类对象
v_emp.change_emp_sal_proc(3800) ; --修改7369工资
DBMS_OUTPUT.put_line('7369雇员工资:' || v_emp.get_emp_sal_fun()) ;
DBMS_OUTPUT.put_line('10部门工资总和:' ||emp_object.get_dept_sal_sum_fun(10)) ;-- 通过类调用
emp_object.change_dept_sal_proc(10,7000) ; --通过类调用
END ;
/
此时的程序分别采用了对象调用MEMBER函数并通过类调用STATIC函数的方式进行了类的功能操作。通过此时的操作可以发现,STATIC函数完全独立类之外,并且无法通过对象进行调用
- 构造函数
- 说明:当创建一个类的对象时,如果希望可以自动完成某些操作,例如为对象中的属性赋值,可以利用构造函数;
- 定义要求:
- 构造函数的名称必须与类名称保持一致;
- 构造函数必须使用CONSTRUCTOR关键字进行定义;
- 构造函数必须定义返回值,且返回值类型必须为SELF AS RESULT;
- 构造函数也可以进行重载,重载的构造函数参数的类型及个数不同;
- 默认的构造函数需要传入全部属性的值;
- 示例1:定义类规范
CREATE OR REPLACE TYPE emp_object AS OBJECT(
atri_empno NUMBER(4) ,-- 雇员编号
atri_sal NUMBER(7,2) ,-- 雇员工资
atri_comm NUMBER(7,2) ,-- 雇员佣金
--定义构造函数,只接收雇员编号
CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER) RETURN SELF AS RESULT ,
--重载构造函数,接收雇员编号及佣金
CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER , p_comm NUMBER) RETURN SELF AS RESULT
) NOT FINAL ;
/
本规范使用了CONSTRUCTOR关键定义了一个emp_object类的构造函数,在此构造函数中将只接受雇员编号一个参数;
- 接上例:定义类体,实现类规范
CREATE OR REPLACE TYPE BODY emp_object AS
CONSTRUCTOR FUNCTION emp_object (p_empno NUMBER) RETURN SELF AS RESULT AS
BEGIN
SELF.atri_empno := p_empno ; --保存雇员编号属性
--查询指定雇员的工资,并将其内容赋值给atri_sal属性
SELECT sal INTO SELF.atri_sal FROM emp WHERE empno=p_empno ;
RETURN ;
END ;
CONSTRUCTOR FUNCTION emp_object(p_empno NUMBER , p_comm NUMBER) RETURN SELF AS RESULT AS
BEGIN
SELF.atri_empno := p_empno ;
SELF.atri_comm := p_comm ;
SELF.atri_sal := 200.0 ;-- 为atri_sal设置默认值
RETURN ;
END ;
END ;
/
- 接上例:使用PL/SQL块测试构造函数
DECLARE
v_emp1 emp_object ;
v_emp2 emp_object ;
v_emp3 emp_object ;
BEGIN
v_emp1 := emp_object(7369,3500) ; --自定义构造函数
v_emp2 := emp_object(7566) ; --自定义构造函数
v_emp3 := emp_object(7839,0.0) ; --默认构造函数
DBMS_OUTPUT.put_line('7369雇员工资:' || v_emp1.atri_sal) ;
DBMS_OUTPUT.put_line('7566雇员工资:' || v_emp2.atri_sal) ;
DBMS_OUTPUT.put_line('7839雇员工资:' || v_emp3.atri_sal) ;
END ;
/
此程序使用了3个不同的构造函数进行对象的创建,其中一个为默认生成的构造函数(要接收全部属性内容),而另外两个为用户自定义的构造函数(使用CONSTRUCTOR定义),在用户自定义的构造函数中,会根据传入的雇员编号查找此雇员的工资,并将查询出来的结果赋值给atri_sal属性。而另外一个构造函数会使用一个默认的数值为atri_sal属性赋值
- 定义MAP与ORDER函数
- 说明:当用户声明了多个类对象后,如果要对这些对象的信息进行排序,就不能按照NUMBER或VARCHAR2这种基本数据类型的方式进行排序了,必须专门指定比较的规则;
- 设置比较规则通过两个函数完成:
- MAP函数:使用MAP定义的函数将会按照用户定义的数据组合值区大小,然后利用ORDER BY子句进行排序;
- ORDER函数:ORDER函数与MAP函数类似,也是定义了一个排序规则,在进行数据排序时会默认调用。同时ORDER函数还可以比较两个对象的大小关系,所以如果要比较多个对象时ORDER函数会被重复调用,性能不如MAP函数;
- 提示:当用户定义一个类时,这两种函数只能2选1;
- 示例1:在类规范中定义MAP函数
CREATE OR REPLACE TYPE emp_object_map AS OBJECT(
atri_empno NUMBER(4) , --雇员编号
atri_ename VARCHAR2(10) , --雇员姓名
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
--定义MAP函数,此函数会在进行排序时自动调用
MAP MEMBER FUNCTION compare RETURN NUMBER
) NOT FINAL ;
/
本类中使用MAP关键字定义了一个compare()函数,同时此函数返回一个数字,,该数字为用户自定义的一个排序规则组合
- 接上例:定义类体实现MAP函数
CREATE OR REPLACE TYPE BODY emp_object_map AS
MAP MEMBER FUNCTION compare RETURN NUMBER AS
BEGIN
RETURN SELF.atri_sal + SELF.atri_comm ;
END ;
END ;
/
在类体中实现了compare()函数,同时在此函数中返回的是"工资+佣金"的数据组合,这样在使用ORDER BY排序时,将采用此函数的返回值进行大小排序
- 接上例:编写测试用数据库创建脚本
--按照emp_object_map的结构创建一张新的数据表,这样就可以使用MAP函数进行排序
CREATE TABLE emp_object_map_tab OF emp_object_map ;
INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7369,'SMITH',800,0) ;
INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7902,'FORD',3000,0) ;
INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7499,'ALLEN',1600,300) ;
INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7521,'WARD',1250,500) ;
INSERT INTO emp_object_map_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7839,'KING',5000,0) ;
COMMIT ;
- 接上例:通过查询实现排序
SELECT VALUE(e) ve , e.atri_empno , e.atri_ename , e.atri_sal+e.atri_comm
FROM emp_object_map_tab e
ORDER BY ve ;
在本程序中,使用了一个VALUE()函数将emp_object_map_tab表中的数据取出,当利用ORDER BY进行排序时,就会自动调用emp_object_map类中的MAP函数(compare)实现数据的组合后进行排序
使用MAP函数可以实现一组数据组合排序,而使用ORDER函数可以实现两个对象间的排序
- 示例2:定义类规范使用ORDER定义函数
CREATE OR REPLACE TYPE emp_object_order AS OBJECT(
atri_empno NUMBER(4) , --雇员编号
atri_ename VARCHAR2(10) , --雇员姓名
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
--定义ORDER函数,此函数可以用于两个对象间的比较
ORDER MEMBER FUNCTION compare(obj emp_object_order) RETURN NUMBER
) NOT FINAL ;
/
本程序将之前的MAP声明修改为ORDER声明,同时在compare()函数中传递了一个emp_object_order的对象,这样就可以用当前对象的数据与传入的对象数据进行比较
- 接上例:定义类体实现类规范,同时实现ORDER类型函数。
CREATE OR REPLACE TYPE BODY emp_object_order AS
ORDER MEMBER FUNCTION compare(obj emp_object_order) RETURN NUMBER AS
BEGIN
IF (SELF.atri_sal + SELF.atri_comm) > (obj.atri_sal + obj.atri_comm) THEN
RETURN 1 ;
ELSIF (SELF.atri_sal + SELF.atri_comm) < (obj.atri_sal + obj.atri_comm) THEN
RETURN -1 ;
ELSE
RETURN 0 ;
END IF ;
END ;
END ;
/
- 接上例:定义PL/SQL块进行对象排序
DECLARE
v_emp1 emp_object_order ;
v_emp2 emp_object_order ;
BEGIN
v_emp1 := emp_object_order(7499,'ALLEN',1600,300) ;
v_emp2 := emp_object_order(7521,'WARD',1250,500) ;
IF v_emp1 > v_emp2 THEN
DBMS_OUTPUT.put_line('7499的工资高于7521的工资。') ;
ELSIF v_emp1 < v_emp2 THEN
DBMS_OUTPUT.put_line('7499的工资低于7521的工资。') ;
ELSE
DBMS_OUTPUT.put_line('7499的工资与7521的工资相同。') ;
END IF ;
END ;
/
- 接上例:除了在PL/SQL中进行比较之外,也可以利用此类型创建数据表通过ORDER BY进行排序
- 创建数据表
--根据emp_object_order创建数据表
CREATE TABLE emp_object_order_tab OF emp_object_order ;
INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7369,'SMITH',800,0) ;
INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7902,'FORD',3000,0) ;
INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7499,'ALLEN',1600,300) ;
INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7521,'WARD',1250,500) ;
INSERT INTO emp_object_order_tab(atri_empno,atri_ename,atri_sal,atri_comm) VALUES (7839,'KING',5000,0) ;
COMMIT ;
- 进行数据查询,同时使用ORDER BY排序
SELECT VALUE(e) ve , e.atri_empno , e.atri_ename , e.atri_sal+e.atri_comm
FROM emp_object_order_tab e
ORDER BY ve ;
- 对象嵌套关系
- 说明:利用PL/SQL的面向对象编程除了可以将基本数据类型定义为属性之外,还可以结合对象的引用传递方式,进行对象类型的嵌套;
- 示例1:定义类规范
--删除emp_object
DROP TYPE emp_object ;
--定义部门类
CREATE OR REPLACE TYPE dept_object AS OBJECT (
atri_deptno NUMBER(2) , --部门编号
atri_dname VARCHAR2(14) , --部门名称
atri_loc VARCHAR2(13) , --部门位置
--取得对象信息
MEMBER FUNCTION tostring RETURN VARCHAR2
) NOT FINAL ;
/
--定义雇员类,每一个雇员属于一个部门,所以设置了一个atri_dept的属性
CREATE OR REPLACE TYPE emp_object AS OBJECT(
atri_empno NUMBER(4) , --雇员编号
atri_ename VARCHAR2(10) , --雇员姓名
atri_job VARCHAR2(9) , --雇员职位
atri_hiredate DATE , --雇佣日期
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
atri_dept dept_object , --雇员部门
--取得对象信息
MEMBER FUNCTION tostring RETURN VARCHAR2
) NOT FINAL ;
/
本程序定义了两个类规范(dept_object,emp_object),由于每一位雇员都有一个自己的部门信息,所以在emp_object类中设置了一个dept_object类型的属性,同时本程序在两个类规范中都定义了tostring()函数,此函数将返回对象的基本信息
- 接上例:定义类体实现类规范
--定义dept_object类体
CREATE OR REPLACE TYPE BODY dept_object AS
MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '部门编号:' || SELF.atri_deptno || ',名称:' || SELF.atri_dname || ',位置:' || SELF.atri_loc ;
END ;
END ;
/
--定义emp_object类体
CREATE OR REPLACE TYPE BODY emp_object AS
MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '雇员编号:' || SELF.atri_empno || ',姓名:' || SELF.atri_ename ||
',职位:' || SELF.atri_job || ',雇佣日期:' || TO_CHAR(SELF.atri_hiredate,'yyyy-mm-dd') ||
',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ;
END ;
END ;
/
- 接上例:编写PL/SQL块验证关系
DECLARE
v_dept dept_object ;
v_emp emp_object ;
BEGIN
--首先定义部门对象,此对象需要通过emp_object类的构造方法保存到v_emp对象属性之中
v_dept := dept_object(10,'ACCOUNTING','NEW YORK') ;
--定义雇员对象,传递此雇员所属的部门对象
v_emp := emp_object(7839,'KING','PRESIDENT',TO_DATE('1981-11-11','yyyy-mm-dd'),5000,null,v_dept) ;
--直接输出雇员的完整信息
DBMS_OUTPUT.put_line(v_emp.tostring()) ;
--根据信息找到其对应的部门信息
DBMS_OUTPUT.put_line(v_emp.atri_dept.tostring()) ;
END ;
/
- 继承性
- 说明:在PL/SQL中实现集成,可以利用UNDER关键实现
- 示例1:定义父类 —— person_object
--定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER , --人员编号
atri_name VARCHAR2(10) , --人员姓名
atri_sex VARCHAR2(10) , --人员性别
MEMBER FUNCTION get_person_info_fun RETURN VARCHAR2
) NOT FINAL ;
/
--定义Person类体
CREATE OR REPLACE TYPE BODY person_object AS
MEMBER FUNCTION get_person_info_fun RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ;
END ;
END ;
/
- 接上例:定义子类 —— emp_object
--定义Emp类规范,此类为Person子类
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9) , --雇员职位
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
MEMBER FUNCTION get_emp_info_fun RETURN VARCHAR2
) ;
/
--定义Emp类体
CREATE OR REPLACE TYPE BODY emp_object AS
MEMBER FUNCTION get_emp_info_fun RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ||
',职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ;
END ;
END ;
/
- 接上例:利用PL/SQL程序块测试
DECLARE
v_emp emp_object ;
BEGIN
--此处必须明确写出父类与子类的全部参数
-- person_object类需要传入三个参数:人员编号、姓名、性别
-- emp_object类需要传入三个参数:职位、工资、佣金
v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ;
DBMS_OUTPUT.put_line('person_object类的函数:' || v_emp.get_person_info_fun()) ;
DBMS_OUTPUT.put_line('emp_object类的函数:' || v_emp.get_emp_info_fun()) ;
END ;
/
程序运行结果:
person_object类的函数:人员编号:7369,姓名:SMITH,性别:FEMALE
emp_object类的函数:人员编号:7369,姓名:SMITH,性别:FEMALE,职位:CLERK,工资:800,佣金:0
- 函数覆写
- 说明:子类要覆写父类的函数,必须在定义时,使用OVERRIDING关键字,定义某一个函数为覆写函数;
- 示例1:定义程序,实现函数的覆写
--定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER , --人员编号
atri_name VARCHAR2(10) , --人员姓名
atri_sex VARCHAR2(10) , --人员性别
MEMBER FUNCTION tostring RETURN VARCHAR2
) NOT FINAL ;
/
--定义Person类体
CREATE OR REPLACE TYPE BODY person_object AS
MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ;
END ;
END ;
/
--定义Emp类规范,此类为Person子类
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9) , --雇员职位
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
--此函数名称与父类函数名称一样,所以此处为函数的覆写
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2
) ;
/
--定义Emp类体
CREATE OR REPLACE TYPE BODY emp_object AS
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ||
'职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ;
END ;
END ;
/
此时在emp_object类中明确使用了OVERRIDING覆写了person_object类中的tostring()函数,这样emp_object类体中就可以继续使用此函数名称
- 接上例:编写PL/SQL块测试程序
DECLARE
v_emp emp_object ;
BEGIN
--此处必须明确写出父类与子类的全部参数
-- person_object类需要传入三个参数:人员编号、姓名、性别
-- emp_object类需要传入三个参数:职位、工资、佣金
v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ;
DBMS_OUTPUT.put_line(v_emp.tostring()) ;
END ;
/
- 对象多态性
- 多态体现在以下两个方面:
- 函数的多态性:体现为函数的重载与覆写;
- 对象的多态性:子类对象可以为父类对象进行实例化;
- 示例1:此示例继续沿用笔记七的例子中的person_object和emp_object类,同时为person_object类增加一个student_object子类;
- 在原有程序基础上增加新的子类
-- 定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER , --人员编号
atri_name VARCHAR2(10) , --人员姓名
atri_sex VARCHAR2(10) , --人员性别
MEMBER FUNCTION tostring RETURN VARCHAR2
) NOT FINAL ;
/
-- 定义Person类体
CREATE OR REPLACE TYPE BODY person_object AS
MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ;
END ;
END ;
/
-- 定义Emp类规范,此类为Person子类
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9) , --雇员职位
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
--此函数名称与父类函数名称一样,所以此处为函数的覆写
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2
) ;
/
-- 定义Emp类体
CREATE OR REPLACE TYPE BODY emp_object AS
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ||
'职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ;
END ;
END ;
/
--定义Student类规范,此类为Person子类
CREATE OR REPLACE TYPE student_object UNDER person_object(
atri_school VARCHAR2(15) ,
atri_score NUMBER(5,2) ,
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2
) ;
/
--定义Student类体
CREATE OR REPLACE TYPE BODY student_object AS
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ||
'学校:' || SELF.atri_school || ',成绩:' || SELF.atri_score ;
END ;
END ;
/
person_object类中存在两个子类,即emp_object和student_object,而且这两个子类都覆写了person_object类中的tostring()函数;
- 通过两个子类为person_object类对象实例化:
DECLARE
v_emp person_object ; --声明person_object类对象
v_student person_object ; --声明person_object类对象
BEGIN
--对象向上转型
v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ;
v_student := student_object(7566,'ALLEN','FEMALE','MLDN',99.9) ;
DBMS_OUTPUT.put_line('【雇员信息】' || v_emp.tostring()) ;
DBMS_OUTPUT.put_line('【学生信息】' || v_student.tostring()) ;
END ;
/
程序声明了person_object类的对象(v_emp,v_student),而后这两个对象分别通过不同的子类进行实例化,之后都可以使用父类对象进行接收,而在调用tostring()函数时执行的是不同类中覆写之后的操作
- 使用FINAL关键字
- 说明:可以利用FINAL关键字定义不能被继承的类与不能被覆写的函数;
- 示例1:使用FINAL定义的类不能被继承
--定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER
) FINAL ; -- 不管是否写此句默认均为FINAL
/
--定义Emp类规范,但是此时由于person_object类无法继承,所以出现错误
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9)
) ;
/
此时的程序在创建emp_object子类时会出现"PLS-00590:正在尝试创建一个最终类型的子类型"错误提示消息,所以使用FINAL声明的类不能被集成
- 示例2:使用FINAL定义的函数不能被子类覆写
--定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER ,
FINAL MEMBER FUNCTION tostring RETURN VARCHAR2
) NOT FINAL ; --不管是否写此句默认均为FINAL
/
--定义Emp类规范,但是此时由于person_object类无法继承,所以出现错误
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9) ,
--错误:此处无法覆写tostring()函数
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2
) ;
/
- 定义抽象函数
- 说明:抽象函数是指,类中的函数不希望被类对象直接使用,需要通过该类的子类来实现。在定义函数时,使用NOT INSTANTIABLE标记即可;同时,包含抽象函数所在的类也必须使用NOT INSTANTIABLE定义,这样的类也同样被称为抽象类
- 示例1:定义抽象类与抽象函数
DROP TYPE emp_object ;
-- 定义Person类规范
CREATE OR REPLACE TYPE person_object AS OBJECT (
atri_pid NUMBER , --人员编号
atri_name VARCHAR2(10) , --人员姓名
atri_sex VARCHAR2(10) , --人员性别
NOT INSTANTIABLE MEMBER FUNCTION tostring RETURN VARCHAR2 --定义抽象方法
) NOT FINALNOT INSTANTIABLE ; --此处必须使用NOT INSTANTIABLE声明类
/
-- 定义Emp类规范,此类为Person子类
CREATE OR REPLACE TYPE emp_object UNDER person_object (
atri_job VARCHAR2(9) , --雇员职位
atri_sal NUMBER(7,2) , --雇员工资
atri_comm NUMBER(7,2) , --雇员佣金
--此函数名称与父类函数名称一样,所以此处为函数的覆写
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2
) ;
/
-- 定义Emp类体
CREATE OR REPLACE TYPE BODY emp_object AS
OVERRIDING MEMBER FUNCTION tostring RETURN VARCHAR2 AS
BEGIN
RETURN '人员编号:' || SELF.atri_pid || ',姓名:' || SELF.atri_name || ',性别:' || SELF.atri_sex ||
'职位:' || SELF.atri_job || ',工资:' || SELF.atri_sal || ',佣金:' || SELF.atri_comm ;
END ;
END ;
/
本程序在person_object类中定义了一个tostring()的抽象函数,这个函数不能直接被person_object类的对象所使用,必须由该类的子类来实现。所以在定义emp_object类时明确地使用OVERRIDING关键字表示要覆写person_object类的tostring()函数
- 接上例:编写程序进行测试
DECLARE
v_emp person_object ;
BEGIN
--通过子类对象为父类实例化
v_emp := emp_object(7369,'SMITH','FEMALE','CLERK',800.0,0.0) ;
DBMS_OUTPUT.put_line(v_emp.tostring()) ;
END ;
/
- Oracle12C--操作类中的其他结构(65)
- Oracle12C--约束的其他操作(十)
- Oracle12C--批量操作(三十四)
- oracle12C--处理游标操作(62)
- oracle12c数据库的简单操作
- .net 互操作之p/invoke- 数据封送(结构体中的字符串,其他字段,内存布局)(4)
- 远程连接centos7中的oracle12c
- 集合中的其他类
- API操作其他程序中的按钮
- opencv中的Mat结构操作
- Oracle12c新特性之基本操作
- 二、Oracle12c中的CDB与PDB
- Oracle12C--重载包中的子程序(五十)
- IO包中的其他类
- IO包中的其他类
- sql中的树结构相关操作
- OpenCV中的结构元素IplConvKernel及操作
- OpenCV中的结构元素IplConvKernel及操作
- 基于LIBSVM实现文本分类(python)
- 搭建SolrCloud集群Could not find or load main class org.apache.solr.cloud.ZkCLI
- 约瑟夫,嘿嘿,你被ko了 。还有一点小感悟
- 图像类型的转换
- 观察者模式应用场景实例
- Oracle12C--操作类中的其他结构(65)
- Python正则表达式
- 从尾到头打印链表
- python正则表达式
- 班级成员表
- 【转】Linux下文件属性(drwxr-xr-x)详解以及(-rwxrwxrwx=777)
- 【多线程简单实例】_beginthreadx实现
- 第一周集训小结
- C++类和对象及其默认成员函数