PL/SQL: Any trick to avoid cloning of objects?
Based on Alex suggestion (use an associative array), I have created a package that encapsulates objects, so we can use them in an abstract way, as if they were references:
create or replace type cla as object -- complex class( name varchar2(10));create or replace package eo as -- package to encapsulate objects type ao_t -- type for hash (associative array) is table of cla index by varchar2(100); o ao_t; -- hash of objectsend;declare o1 varchar2(100); o2 varchar2(100);begin o1 := 'o1'; -- objects are hash indexes now eo.o(o1) := new cla('hi'); -- store new object into the hash o2 := o1; -- assign object == assign index eo.o(o1).name := 'bye'; -- change object attribute dbms_output.put_line('eo.o(o1).name: ' || eo.o(o1).name); dbms_output.put_line('eo.o(o2).name: ' || eo.o(o2).name); -- equal?end;
Now 'bye' is written twice, as expected with object references. The trick is that both o1 and o2 contain the same index (~reference) to the same object. The syntax is a bit more complex, but still very similar to standard object manipulation when accessing both attributes and methods.
Assigning an object to other is exactly as standard object assigning:
o2 := o1;
Same for using an object as a function argument:
afunc(o1);
Internally, afunc() will just use o1 with the same special syntax to access methods or attributes (and no special syntax to assign):
eo.o(o1).attrib := 5;eo.o(o1).method('nice');o3 := o1;
The only requirement to use this trick is to add a hash (type and variable) to the eo package for each class we want to encapsulate.
Update: The index value based on the variable name:
o1 := 'o1';
could be a problem if, for example, we create the object in a funcion, since the function would have to know all values used in the rest of the program in order to avoid repeating a value. A solution is to take the value from the hash size:
o1 := eo.o.count;
That takes us into other problem: The hash content is persitent (since it is into a package), so more and more objects will be added to the hash as we create objects (even if the objects are created by the same function). A solution is to remove the object from the hash when we are done with the object:
eo.o(o1) = null;
So the fixed program would be:
create or replace type cla as object -- complex class( name varchar2(10));create or replace package eo as -- package to encapsulate objects type ao_t -- type for hash (associative array) is table of cla index by varchar2(100); o ao_t; -- hash of objectsend;declare o1 varchar2(100); o2 varchar2(100);begin o1 := eo.o.count; -- index based on hash size eo.o(o1) := new cla('hi'); -- store new object into the hash o2 := o1; -- assign object == assign index eo.o(o1).name := 'bye'; -- change object attribute dbms_output.put_line('eo.o(o1).name: ' || eo.o(o1).name); dbms_output.put_line('eo.o(o2).name: ' || eo.o(o2).name); -- equal? eo.o(o1) = null; -- remove object eo.o(o2) = null; -- remove object (redundant)end;