Как вызвать супер-метод объекта Oracle PL / SQL - PullRequest
6 голосов
/ 20 февраля 2012

Я хотел бы вызвать переопределенный метод 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 Ответ

7 голосов
/ 20 февраля 2012

Чтобы получить доступ к супер методам, попробуйте либо общий вызов, либо обобщенное выражение.Например, используя супертип человека и подтип студента:

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 () для студента для метода person или просто show () для метода студента.

Издокументы, надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...