gpt4 book ai didi

oracle - PL/SQL : Any trick to avoid cloning of objects?

转载 作者:行者123 更新时间:2023-12-02 03:32:46 25 4
gpt4 key购买 nike

如果我们将一个对象变量分配给 pl/sql 中的其他对象变量,则该对象将被克隆,因为 pl/sql 不适用于引用。例如,以下代码将打印两个不同的句子:

create or replace type cla as object    -- class (would be very complex)
(
name varchar2(50)
);

declare
o1 cla;
o2 cla;
begin
o1 := cla('hi cloning world');
o2 := o1;
o1.name = 'goodbye cloning world';

dbms_output.put_line('o1.name: ' || o1.name);
dbms_output.put_line('o2.name: ' || o2.name);
end;

所以我想我可以将对象封装到其他对象(外部对象)中,如果我将外部对象分配给其他外部对象,那么内部对象就不会被克隆:
create or replace type cla as object    -- class (would be very complex)
(
name varchar2(10)
);

create or replace type eo_c as object -- class to encapsulate objects
(
o cla -- encapsulation is easy
);

declare
eo eo_c;
eo2 eo_c;
begin
eo := eo_c( cla('n1') ); -- eo is easy to create
dbms_output.put_line('eo.name: ' || eo.o.name); -- real object is easy to access

eo2 := eo; -- eo_c object is cloned, cla object shouldn't be cloned
eo.o.name := 'n2'; -- if eo.o == eo2.o then we are changing both names
dbms_output.put_line('eo.name: ' || eo.o.name);
dbms_output.put_line('eo2 name: ' || eo2.o.name);
end;

但这又打印了两个不同的句子,所以内部对象也被克隆了。

我可以将对象封装到其他类型的变量中以避免克隆内部对象吗?或者更一般地说,是否有一些技巧可以避免对象的克隆,同时允许一种简单的方法来使用它?

最佳答案

根据 Alex 的建议(使用关联数组),我创建了一个封装对象的包,因此我们可以以抽象的方式使用它们,就好像它们是引用一样:

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 objects
end;


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;

现在 'bye' 写了两次,正如预期的对象引用。诀窍是 o1 和 o2 都包含相同对象的相同索引(~reference)。语法有点复杂,但在访问属性和方法时仍然与标准对象操作非常相似。

将对象分配给其他对象与标准对象分配完全相同:
o2 := o1;

使用对象作为函数参数也是如此:
afunc(o1);

在内部, afunc() 将仅使用具有相同特殊语法的 o1 来访问方法或属性(并且没有要分配的特殊语法):
eo.o(o1).attrib := 5;
eo.o(o1).method('nice');
o3 := o1;

使用这个技巧的唯一要求是为我们要封装的每个类的 eo 包添加一个哈希(类型和变量)。

更新 : 基于变量名的索引值:
o1 := 'o1';

例如,如果我们在函数中创建对象,这可能是一个问题,因为该函数必须知道程序其余部分使用的所有值,以避免重复一个值。一种解决方案是从散列大小中获取值:
o1 := eo.o.count;

这将我们带入另一个问题:散列内容是持久的(因为它是在一个包中),所以当我们创建对象时,越来越多的对象将被添加到散列中(即使这些对象是由同一个函数创建的)。一个解决方案是在我们处理完对象后从哈希中删除该对象:
eo.o(o1) = null;

所以固定的程序是:
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 objects
end;


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;

关于oracle - PL/SQL : Any trick to avoid cloning of objects?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25687106/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com