2012-02-20 57 views
6

Me gustaría llamar a un método PL/SQL reemplazado. He aquí un ejemplo:Cómo llamar a un super método de objeto PL/SQL de Oracle

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

Ahora quiero invocar la versión heredada del método proc. Cuando trato de hacer una conversión explícita como treat(self as test).proc(s); que no se compilará debido PLS-00363: la expresión 'SYS_TREAT' no puede ser utilizado como un destino de la asignación

El cuerpo tipo compila cuando se utiliza una variable local:

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

Pero cuando corro mi ejemplo como este

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

... que arroja ORA-21780: el número máximo de duración de objetos superó.

¿Hay alguna manera de invocar test :: proc (sin serialización/deserialización)?

Y ... después de que se haya llamado al proc, ¿cómo se puede reflejar algún atributo modificado (a saber, n) en obj?


actualización (Gracias, tbone):

me cambió la organización de mis métodos que utilizan métodos de plantilla ('antes' y 'después'). Los agrego cada vez que necesito extender un método.

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

de docs parece que TREAT se usa para acceder a los métodos de subtipo/attribs, no súper. Puedo estar equivocado, pero vea http://docs.oracle.com/cd/E11882_01/appdev.112/e11822/adobjbas.htm – tbone

+0

sí, tiene razón. Los documentos dicen que TRATAR solo puede acceder al subtipo. ¿Pero cómo se supone que debo usar la súper clase? –

Respuesta

6

Para acceder a los métodos súper, intente la invocación general o la expresión generalizada. Por ejemplo, usando un supertipo y subtipo persona estudiante:

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:

Si usted está en 10g, que necesita para organizar las funciones de un poco diferentes, pero misma funcionalidad del niño para llamar el método súper:

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; 

Ahora se llamaría show_super() del estudiante por el método de la persona, o simplemente mostrar() para el método de los estudiantes.

De los documentos, espero que ayude.

+0

Gracias, excelente respuesta. Sin embargo, "AS" se introdujo con 11g. Supongo que eso significa que no hay forma de 10g. –

+0

@ hal9000 ver mis actualizaciones arriba – tbone

Cuestiones relacionadas