首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PL/SQL:避免克隆对象的任何技巧?

PL/SQL:避免克隆对象的任何技巧?
EN

Stack Overflow用户
提问于 2014-09-05 13:32:10
回答 1查看 1.3K关注 0票数 4

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

代码语言:javascript
运行
复制
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;

因此,我认为可以将对象封装到其他对象(外部对象)中,如果将外部对象分配给其他外部对象,那么内部对象就不会被克隆:

代码语言:javascript
运行
复制
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;

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

我能否将对象封装到其他类型的变量中以避免内部对象的克隆?或者更广泛地说,是否有一些技巧来避免对象的克隆,同时允许一个简单的方法来处理它呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-08 09:25:47

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

代码语言:javascript
运行
复制
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都包含同一个对象的相同索引(~引用)。语法有点复杂,但在访问属性和方法时仍然非常类似于标准对象操作。

将对象分配给其他对象与标准对象赋值完全相同:

代码语言:javascript
运行
复制
o2 := o1;

使用对象作为函数参数也一样:

代码语言:javascript
运行
复制
afunc(o1);

在内部,afunc()将只使用具有相同特殊语法的o1来访问方法或属性(而不需要分配特殊的语法):

代码语言:javascript
运行
复制
eo.o(o1).attrib := 5;
eo.o(o1).method('nice');
o3 := o1;

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

更新:基于变量名的索引值:

代码语言:javascript
运行
复制
o1 := 'o1';

例如,如果我们在Fun广子中创建对象,则可能会出现问题,因为函数必须知道程序其余部分中使用的所有值,以避免重复一个值。解决方案是从散列大小中获取值:

代码语言:javascript
运行
复制
o1 := eo.o.count;

这就给我们带来了其他问题:散列内容是持久化的(因为它是包中的),所以在创建对象时,会有越来越多的对象被添加到哈希中(即使对象是由同一个函数创建的)。一种解决方案是在完成对象操作时将对象从哈希中移除:

代码语言:javascript
运行
复制
eo.o(o1) = null;

所以固定的程序是:

代码语言:javascript
运行
复制
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;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25687106

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档