2016年3月12日 星期六

物件導向三(一對多、繼承、覆寫)(PL/SQL 三十)

類似Hibernate的東西,可以一對多

※一對多

※宣告與實作 DEPT

CREATE OR REPLACE TYPE dept_obj IS OBJECT(
    attr_deptno NUMBER(2),
    attr_dname VARCHAR2(14),
    attr_loc VARCHAR2(13),
    
    MEMBER FUNCTION to_string RETURN VARCHAR2
) NOT FINAL;
    
    
    
CREATE OR REPLACE TYPE BODY dept_obj IS
    MEMBER FUNCTION to_string RETURN VARCHAR2 IS
    BEGIN
        RETURN SELF.attr_deptno || ':' || SELF.attr_dname || ':' || SELF.attr_loc;
    END;
END;



※宣告與實作 EMP

CREATE OR REPLACE TYPE emp_obj IS OBJECT(
    attr_empno NUMBER(4),
    attr_ename VARCHAR2(10),
    attr_job VARCHAR2(9),
    attr_mgr NUMBER(4),
    attr_hiredate DATE,
    attr_sal NUMBER(7,2),
    attr_comm NUMBER(7,2),
    attr_deptno dept_obj,
    
    MEMBER FUNCTION to_string RETURN VARCHAR2
) NOT FINAL;
    
    
    
CREATE OR REPLACE TYPE BODY emp_obj IS
    MEMBER FUNCTION to_string RETURN VARCHAR2 IS
    BEGIN
        RETURN SELF.attr_empno || ':' || SELF.attr_ename || ':' || SELF.attr_sal || ':' || SELF.attr_comm;
    END;
END;

※注意最後一個屬性的型態



※測試

DECLARE
    o_dept dept_obj;
    o_emp emp_obj;
BEGIN
    o_dept := dept_obj(30, 'SALES', 'CHICAGO');
    o_emp := emp_obj(7698, 'BLAKE', 'MANAGER', 7839, to_date('1-5-1981', 'dd-mm-yyyy'), 2850, NULL, o_dept);
    
    DBMS_OUTPUT.PUT_LINE(o_emp.to_string());
    DBMS_OUTPUT.PUT_LINE(o_emp.attr_sal);
    DBMS_OUTPUT.PUT_LINE(o_emp.attr_deptno.to_string());
END;

※注意o_emp的最後一個參數型態

※結果:
7698:BLAKE:2850:
2850
30:SALES:CHICAGO



※繼承


※父類別的宣告與實作

CREATE OR REPLACE TYPE father_obj IS OBJECT(
    attr_empno NUMBER(4),
    attr_ename VARCHAR2(10),
    attr_job VARCHAR2(9),
    
    MEMBER FUNCTION f_tostring RETURN VARCHAR2
) NOT FINAL;
    
    
    
CREATE OR REPLACE TYPE BODY father_obj IS
    MEMBER FUNCTION f_tostring RETURN VARCHAR2 IS
    BEGIN
        RETURN SELF.attr_empno || ':' || SELF.attr_ename || ':' || SELF.attr_job;
    END;
END;

※和之前沒什麼不同



※子類別的宣告與實作

CREATE OR REPLACE TYPE son_obj UNDER father_obj(
    attr_sal NUMBER(7,2),
    attr_comm NUMBER(7,2),
    
    MEMBER FUNCTION s_tostring RETURN VARCHAR2
) NOT FINAL;
    
    
    
CREATE OR REPLACE TYPE BODY son_obj IS
    MEMBER FUNCTION s_tostring RETURN VARCHAR2 IS
    BEGIN
        RETURN SELF.attr_ename || ':' || SELF.attr_sal;
    END;
END;

※要使用UNDER關鍵字,相當於java的extend,「IS OBJECT」就不需要了



※測試

DECLARE
    son son_obj;
BEGIN
    son := son_obj(7698, 'BLAKE', 'MANAGER', 2850, NULL);
    DBMS_OUTPUT.PUT_LINE(son.f_tostring);
    DBMS_OUTPUT.PUT_LINE(son.s_tostring);
END;

※要使用son時,要先從父類別的建構子開使塞值,塞完換子類別



※覆寫

就是要覆寫父類別的方法,將上面的父類別拿來改(必需先刪除子類別才行)
我只將父類別的方法改成to_string,就不貼出來了


※子類別的宣告與實作

CREATE OR REPLACE TYPE son_obj UNDER father_obj(
    attr_sal NUMBER(7,2),
    attr_comm NUMBER(7,2),
    
    OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2
) NOT FINAL;
    
    
    
CREATE OR REPLACE TYPE BODY son_obj IS
    OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 IS
    BEGIN
        RETURN SELF.attr_ename || ':' || SELF.attr_sal;
    END;
END;

※一定要加OVERRIDING關鍵字;如果不加,編譯時,錯誤訊息也有提示,如「PLS-00636: 覆寫方法必須有 OVERRIDING 關鍵字」



※測試

DECLARE
    son son_obj;
    papa father_obj;
BEGIN
    son := son_obj(7698, 'BLAKE', 'MANAGER', 2850, NULL);
    DBMS_OUTPUT.PUT_LINE(son.to_string);
    
    papa := father_obj(7698, 'BLAKE', 'MANAGER');
    DBMS_OUTPUT.PUT_LINE(papa.to_string);
END;

※測試和繼承一樣,也可以只呼叫父類別

沒有留言:

張貼留言