2012-02-20 53 views
6

我想調用重寫的PL/SQL方法。這裏有一個例子:如何調用Oracle PL/SQL對象超級方法

-- super class 
create or replace type test as object 
(
    n number, 
    member procedure proc(SELF in out nocopy test, s varchar2) 
) 
alter type test not final 
/

create or replace type body test is 
    member procedure proc(SELF in out nocopy test, s varchar2) is 
    begin 
    dbms_output.put_line('test1: n='||nvl(self.n, 'null')||' s='||s); 
    self.n := to_number(s); 
    end; 
end; 
/

-- derived class 
create or replace type test2 under test 
(
    overriding member procedure proc(SELF in out nocopy test2, s varchar2) 
) 
/

現在我想調用的方法proc的繼承版本。當我嘗試做這樣treat(self as test).proc(s);有明確的轉換,將無法編譯,因爲PLS-00363:表達式「SYS_TREAT」不能作爲分配對象

當我使用一個局部變量的類型身體編譯:

create or replace type body test2 is 
    overriding member procedure proc(SELF in out nocopy test2, s varchar2) is 
    O test; 
    begin 
    O := treat(self as test); 
    O.proc(s); 
    end; 
end; 
/

但是當我運行像這樣

declare 
    obj test2; 
begin 
    obj := test2(0); 
    obj.proc('1'); 
end; 

我的例子......它拋出ORA-21780:對象持續時間的數量上限。

有什麼辦法可以調用test :: proc(不需要序列化/反序列化)嗎?

...... proc被調用後,如何更改屬性(即n)如何反映在obj


更新(謝謝,TBONE):

我改變了使用模板方法( '之前' 和 '之後'),我的方法組織。無論何時我需要擴展一個方法,我都會添加它們。

create or replace type test as object 
(
    n number, 
    member procedure proc  (SELF in out nocopy test, s varchar2), 
    member procedure afterProc (SELF in out nocopy test, s varchar2) 
    member procedure beforeProc(SELF in out nocopy test, s varchar2), 
) 
not final 
/

create or replace type body test is 
    member procedure proc(SELF in out nocopy test, s varchar2) is 
    begin 
    beforeProc(s); 
    dbms_output.put_line('test1: n='||nvl(n, 'null')||' s='||s); 
    n := to_number(s); 
    afterProc(s); 
    end; 
    member procedure afterProc (SELF in out nocopy test, s varchar2) is begin null; end; 
    member procedure beforeProc(SELF in out nocopy test, s varchar2) is begin null; end; 
end; 
/
+1

docs看起來像TREAT用於訪問子類型方法/ attribs,而不是超級。我可能是錯的,但請參閱http://docs.oracle.com/cd/E11882_01/appdev.112/e11822/adobjbas.htm – tbone 2012-02-20 15:36:40

+0

是的,你是對的。文檔說TREAT只能訪問子類型。但我應該如何使用超類? – 2012-02-20 15:59:35

回答

6

要訪問超級方法,請嘗試通用調用或通用表達式。例如,使用一個人超和學生亞型:

CREATE OR REPLACE TYPE person_typ AS OBJECT (
    idno number, 
    name varchar2(30), 
    phone varchar2(20), 
    MAP MEMBER FUNCTION get_idno RETURN NUMBER, 
    MEMBER FUNCTION show RETURN VARCHAR2) 
NOT FINAL; 

CREATE OR REPLACE TYPE BODY person_typ AS 
    MAP MEMBER FUNCTION get_idno RETURN NUMBER IS 
    BEGIN 
    RETURN idno; 
    END; 
    MEMBER FUNCTION show RETURN VARCHAR2 IS 
    BEGIN 
    -- function that can be overriden by subtypes MEMBER FUNCTION show RETURN VARCHAR2 IS BEGIN 
    RETURN 'Id: ' || TO_CHAR(idno) || ', Name: ' || name; 
    END; 
END; 

CREATE TYPE student_typ UNDER person_typ (
    dept_id NUMBER, 
    major VARCHAR2(30), 
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2) 
NOT FINAL; 

CREATE TYPE BODY student_typ AS 
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS 
    BEGIN 
    RETURN (self AS person_typ).show || ' -- Major: ' || major ; 
    END; 
END; 

-- Using Generalized Invocation 
DECLARE 
myvar student_typ := student_typ(100, 'Sam', '6505556666', 100, 'Math'); 
name VARCHAR2(100); 
BEGIN 
name := (myvar AS person_typ).show; --Generalized invocation 
END; 

-- Using Generalized Expression 
DECLARE 
myvar2 student_typ := student_typ(101, 'Sam', '6505556666', 100, 'Math'); 
name2 VARCHAR2(100); 
BEGIN 
name2 := person_typ.show((myvar2 AS person_typ)); -- Generalized expression 
END; 

編輯:

如果您在10g中,你需要組織的功能有點不同,但是從孩子相同的功能調用超級方法:

CREATE TYPE BODY person_typ AS 
    MAP MEMBER FUNCTION get_idno RETURN NUMBER IS 
    BEGIN 
    RETURN idno; 
    END; 
    -- static function that can be called by subtypes 
    STATIC FUNCTION show_super (person_obj in person_typ) RETURN VARCHAR2 IS 
    BEGIN 
    RETURN 'Id: ' || TO_CHAR(person_obj.idno) || ', Name: ' || person_obj.name; 
    END; 
    -- function that can be overriden by subtypes 
    MEMBER FUNCTION show RETURN VARCHAR2 IS 
    BEGIN 
    RETURN person_typ.show_super (SELF); 
    END; 
END; 

CREATE TYPE student_typ UNDER person_typ ( 
    dept_id NUMBER, 
    major VARCHAR2(30), 
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2) 
    NOT FINAL; 

CREATE TYPE BODY student_typ AS 
    OVERRIDING MEMBER FUNCTION show RETURN VARCHAR2 IS 
    BEGIN 
    RETURN person_typ.show_super (SELF) || ' -- Major: ' || major ; 
    END; 
END; 

現在你會打電話從學生show_super()的人的方法,或只是表明()爲學生的方法。

從文檔,希望有所幫助。

+0

謝謝,很好的答案。但是,11g引入了「AS」。我想這意味着10g沒有辦法。 – 2012-02-20 17:01:58

+0

@ hal9000在上面看到我的更新 – tbone 2012-02-20 18:17:52