2012-02-20 62 views
6

Tôi muốn gọi phương thức PL/SQL đã ghi đè. Dưới đây là ví dụ:Cách gọi phương thức siêu đối tượng 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) 
) 
/

Bây giờ tôi muốn gọi phiên bản kế thừa của phương pháp proc. Khi tôi cố gắng làm một diễn viên rõ ràng như treat(self as test).proc(s); nó sẽ không biên dịch vì PLS-00.363: biểu hiện 'SYS_TREAT' không thể được sử dụng như một mục tiêu chuyển nhượng

Cơ thể loại biên dịch khi tôi sử dụng một biến địa phương:

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

Nhưng khi tôi chạy ví dụ của tôi như thế này

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

... nó ném ORA-21.780: số lượng tối đa những khoảng thời gian đối tượng vượt quá.

Có cách nào để gọi kiểm tra :: proc (không serialize/deserializing) không?

Và ... sau khi proc đã được gọi, làm thế nào có thể thay đổi bất kỳ thuộc tính (cụ thể là n) được phản ánh trong obj?


Cập nhật (Cảm ơn, tbone):

tôi đã thay đổi việc tổ chức các phương pháp của tôi sử dụng phương pháp mẫu ('trước' và 'sau khi'). Tôi thêm chúng bất cứ khi nào tôi cần phải mở rộng một phương pháp.

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

từ tài liệu có vẻ như TREAT được sử dụng để truy cập các phương thức/attribs phụ, không phải siêu. Tôi có thể sai, nhưng hãy xem http://docs.oracle.com/cd/E11882_01/appdev.112/e11822/adobjbas.htm – tbone

+0

có, bạn nói đúng. Các tài liệu nói TREAT chỉ có thể truy cập vào loại phụ. Nhưng làm thế nào tôi có thể sử dụng các lớp siêu? –

Trả lời

6

Để truy cập các phương thức siêu, hãy thử lời gọi chung hoặc biểu thức khái quát. Ví dụ, sử dụng một siêu kiểu người và kiểu phụ sinh viên:

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:

Nếu bạn đang ở trên 10g, bạn sẽ cần phải tổ chức thực hiện chức năng một chút khác nhau, nhưng cùng một chức năng từ đứa trẻ để gọi phương thức siêu:

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; 

Bây giờ bạn gọi show_super() từ sinh viên cho phương thức cá nhân hoặc chỉ hiển thị() cho phương pháp của sinh viên.

Từ tài liệu, hy vọng điều đó sẽ hữu ích.

+0

Cảm ơn, câu trả lời tuyệt vời. Tuy nhiên "AS" đã được giới thiệu với 11g. Tôi đoán điều đó có nghĩa là không có cách nào cho 10g. –

+0

@ hal9000 xem các cập nhật của tôi ở trên – tbone

Các vấn đề liên quan