2012-02-20 10 views
6

Vorrei chiamare un metodo PL/SQL sovrascritto. Ecco un esempio:Come chiamare un metodo Super 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) 
) 
/

Ora voglio richiamare la versione ereditata del metodo proc. Quando provo a fare un cast esplicito come treat(self as test).proc(s); non si compila a causa di PLS-00363: l'espressione 'SYS_TREAT' non può essere utilizzato come destinazione di assegnazione

Il corpo di tipo compila quando uso una variabile locale:

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; 
/

Ma quando eseguo il mio esempio come questo

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

... getta ORA-21780: numero massimo di durata degli oggetti superato.

C'è un modo per chiamare test :: proc (senza serializzazione/deserializzazione)?

E ... dopo che proc è stato chiamato, come possono essere riflessi eventuali attributi modificati (ovvero n) in obj?


Aggiornamento (Grazie, tbone):

ho cambiato l'organizzazione dei miei metodi che utilizzano metodi di template ('prima' e 'dopo'). Li aggiungo ogni volta che ho bisogno di estendere un metodo.

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

da documenti sembra che TREAT sia utilizzato per accedere ai metodi/attributi di sottotipo, non super. Potrei sbagliarmi, ma vedi http://docs.oracle.com/cd/E11882_01/appdev.112/e11822/adobjbas.htm – tbone

+0

sì, hai ragione. I documenti dicono che TREAT può solo accedere al sottotipo. Ma come dovrei usare la super classe? –

risposta

6

per accedere ai metodi eccellenti, provare uno invocazione generale o l'espressione generalizzata. Ad esempio, utilizzando una persona supertipo e studente sottotipo:

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; 

EDIT:

Se siete su 10g, avrete bisogno di organizzare le funzioni un po 'diverse, ma stessa funzionalità dal bambino di chiamare il metodo super:

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; 

Ora si chiamerebbe show_super() da studente per il metodo di persona, o semplicemente mostrare() per il metodo studente.

Dai documenti, sperare che aiuti.

+0

Grazie, ottima risposta. Tuttavia "AS" è stato introdotto con 11g. Immagino che questo significhi che non c'è modo per 10g. –

+0

@ hal9000 vedere i miei aggiornamenti sopra – tbone

Problemi correlati