Как добится вызова по цепочке функций объектного типа возвращающие SELF?
Хочу добится вызова функций по цепочке, как например в C++ или Java. То есть, чтобы функции объектного типа вернули SELF. И тогда можно было бы связать эти вызовы по цепочке. Что-то вроде:
result := objType(1).setValue(2).addValue(1).printf();
Пробовал вернуть тот же тип, но так не работает. Самый упрощённый пример:
create or replace type objType as object (
val int, member function addValue (val int) return objType)
/
create or replace type body objType as
member function addValue (val int) return objType is
begin
self.val := self.val + val;
return self;
end;
end;
/
Выводит такую ошибку:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/14 PLS-00363: expression 'SELF.VAL' cannot be used as an assignment target
Как такое можно реализовать?
Ответы (1 шт):
В функциях первый параметр всегда ссылка на сущность объектного типа SELF. Причём, если она не указана явно, то по умолчанию её режим IN, то есть константная ссылка, о чём и упомянуто в ошибке.
Изменить режим на OUT в этом случае не поможет, так как нельзя изменять сущность объекта пока она не присвоена переменной.
Единственное решение, в функции создать копию на SELF и вернуть её как результат.
Вот результат рабочего примера (код реализации ниже):
select listmaker (tokenList ('abc','def')).pad ('>>','<<').join () result
from dual
/
RESULT
----------------
>>abc<<; >>def<<
Реализация:
create or replace type listmaker as object (
tokens tokenList,
constructor function listmaker (tokens tokenList) return self as result,
member function pad (lval char, rval char) return listmaker,
member function join (delimiter char := '; ') return varchar2
)
/
create or replace type body listmaker as
constructor function listmaker (
self in out listmaker, tokens tokenList) return self as result is
begin
self.tokens := tokens;
return;
end;
member function pad (lval char, rval char) return listmaker is
my listmaker := self;
begin
for i in 1..my.tokens.count loop
my.tokens(i) := lval||my.tokens(i)||rval;
end loop;
return my;
end;
member function join (delimiter char := '; ') return varchar2 is
ret varchar2 (32767);
begin
for i in 1..tokens.count loop ret := ret||tokens(i)||delimiter;
end loop;
return rtrim (ret, delimiter);
end;
end;
/