2012-02-20 19 views
6

Geçersiz kılınan bir PL/SQL yöntemini çağırmak istiyorum. İşte bir örnek: Bir Oracle PL/SQL nesnesi süper yöntemi nasıl çağrılır

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

Şimdi proc yöntemin miras sürümünü çağırmak istiyorum. ifadesi 'SYS_TREAT' bir atama hedefi yerel bir değişken kullandığınızda tipi vücut derler

olarak kullanılamaz: Yapmam çalıştığınızda treat(self as test).proc(s); gibi açık bir döküm bunun yüzünden PLS-00363 derlenmeyecektir

Bu

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

gibi benim örnek çalıştırdığınızda

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

Ama ... ORA-21780 atar: nesne süreleri üst sınırı aşıldı.

Test :: proc (serializing/deserializing olmadan) çağrısının herhangi bir yolu var mı?

Ve ... proc çağrıldıktan sonra, değiştirilen özellikler (n) obj'a nasıl yansıtılır?


Güncelleme (Teşekkürler, tbone):

I ('önce' ve 'sonra') şablonu yöntemlerle yöntemlerimden organizasyonunu değiştirdi. Bir yöntemi genişletmem gerektiğinde onları ekliyorum.

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

görünüyor TREAT gibi alt türü yöntemleri/attribs erişmek için kullanılır, süper değil. Yanılıyor olabilirim, ancak http://docs.oracle.com/cd/E11882_01/appdev.112/e11822/adobjbas.htm – tbone

+0

evet, haklısınız. Doktorlar TREAT'in sadece alt sınıfa erişebileceğini söylüyor. Ama süper sınıfı nasıl kullanmalıyım? –

cevap

6

Süper yöntemlere erişmek için genel çağrı veya genelleştirilmiş ifadeyi deneyin. Örneğin, bir kişi süpertip ve öğrenci alt türünü kullanabilirsiniz:

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; 

DÜZENLEME:

sen 10g üzerinde iseniz, biraz farklı işlevleri düzenlemek gerekir, ama çocuktan aynı işlevselliği aramak için süper yöntemi:

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; 

Şimdi kişi yöntemi için öğrenci show_super() arayacağımı, ya da sadece öğrenci yöntemi için() göstermektedir.

Belgelerden yardımcı olacağını umarız. Docs gibi

+0

Teşekkürler, harika Cevap. Ancak "AS" 11g ile tanıtıldı. Sanırım bunun anlamı 10g için bir yol yok. –

+0

@ hal9000 güncellemelerimi yukarıda görebilirsiniz – tbone

İlgili konular