是否可以使用其他引用克隆对象?
以下是我正在尝试做的一个示例:我有一个名为TLabel
的{{1}}。现在我想创建一个Label1
,等于Label2
,能够在不相互反映的情况下进行更改。
Ps:我使用Label1
作为示例,我想复制另一个实例中的任何对象。
在下面的代码中,我尝试更改名称,但引用仍然相同,当更改其中一个时,另一个也会更改。
TLabel
答案 0 :(得分:8)
可以为TComponent后代编写克隆函数:
function CloneComponent(aSource: TComponent): TComponent;
var mem: TMemoryStream;
begin
mem := TMemoryStream.Create;
try
mem.WriteComponent(aSource);
mem.Seek(0,soFromBeginning);
Result := mem.ReadComponent(nil);
finally
mem.free;
end;
end;
请注意,只有以这种方式复制已发布的属性,以及通过DefineProperties
保存哪些组件的数据。克隆了整数,浮点数,字符串,枚举和集合,但是引用可能存在问题:流系统设计用于保存到文件并从那里读取,因此没有内存地址被转移,而是进行相当复杂的操作来转换它们到字符串路径,包括组件所有者和名称。通常,您需要流式传输所有结构,然后才会保存一些内部关系。
如果您是应该克隆的类的设计者,那么重写Assign方法似乎是更强大的解决方案。
这个TComponent流媒体解决方案的好处是:你能够在不知道前提的情况下克隆一些任意组件,它是什么类。例如,列出各种组件或一些更复杂的结构,然后获取每个组件的完整副本。
答案 1 :(得分:5)
在您的代码中,您正在执行此操作:
cloneOfLabel1 := Label1;
但是,这只是获取其指针的副本,因此它仍将引用原始文件。它不会复制。
最接近你可以得到TPersistent.Assign()
,这需要实现以实际复制属性。 TLabel
未实现Assign
,因此您也无法使用它来创建克隆。
答案是你不能随意克隆对象,除非它继承自TPersistent
和实现Assign
。即便如此,您仍然受Assign
过程的支配,因此它只会复制它设计为复制的属性。 Name
肯定不是其中之一,特别是因为不可能有两个具有相同名称的组件。实际上,即使您为组件的克隆副本设置了唯一名称,也无法通过它引用它,因为它是在运行时创建的。只能通过名称直接引用设计时组件。
在旁注中,记录可以(本质上)使用简单的:=
进行复制,因为记录是值类型而不是类。但是,我确信根据你的例子,这些记录是不可能的。