【问题标题】:Delphi. Clone an object [duplicate]德尔福。克隆一个对象[重复]
【发布时间】:2018-02-11 13:50:14
【问题描述】:

是否可以用另一个引用克隆一个对象?

这是我正在尝试做的一个示例:我有一个名为 Label1TLabel。现在我想创建一个Label2,等于Label1,可以更改而不相互反映。

Ps:我以TLabel为例,我想复制另一个实例中的任何对象。

在下面的代码中,我尝试更改名称,但引用仍然相同,当其中一个更改时,其他的也会更改。

var
    cloneOfLabel1: TLabel;
begin
    Label1.Caption := 'label 1';
    cloneOfLabel1 := Label1;
    cloneOfLabel1.Name := 'label2';
    cloneOfLabel1.Caption := 'label 2';
    cloneOfLabel1.Left := 0;
    cloneOfLabel1.Top := Label1.Top+100;

【问题讨论】:

标签: delphi object


【解决方案1】:

可以为 TComponent 后代编写 Clone 函数:

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 流解决方案的好处是:您可以在不知道它是什么类的情况下克隆一些任意组件。例如,列出各种组件或更复杂的结构,然后获取每个组件的完整副本。

【讨论】:

  • "流媒体系统是为保存到文件而设计的" 确实,所以这被认为是一种 hack。我个人永远不会依赖这个,除非我自己实际上是在创建某种形式的设计师。当然,我们不知道 OP 真正想要完成什么——也许确实需要任意对象。但就像你自己说的,它只适用于published 属性,所以它首先只适用于从TComponent 继承的东西。
  • @JerryDodge 实际上,这就是 IDE 本身在设计时实现组件复制/粘贴的方式。它将复制的组件流式传输到 DFM,然后将 DFM 流式传输到粘贴的组件。这是 VCL 和 FMX 支持克隆对象的唯一官方方式,无需每个类都实现 TPersistent.Assign() 和/或 TPersistent.AssignTo()
【解决方案2】:

在您的代码中,您正在这样做:

cloneOfLabel1 := Label1;

但是,这只是获取其指针的副本,因此它仍会引用原始指针。它不会复制。

你能得到的最接近的来自TPersistent.Assign(),需要实现它才能实际复制属性。 TLabel 没有实现Assign,所以你也不能用它来创建克隆。

答案是不能随意克隆对象,除非它继承自TPersistent并且实现Assign。即便如此,您仍受Assign 过程的支配,因此它只会复制它旨在复制的那些属性。 Name 肯定不是其中之一,尤其是因为不可能有两个同名的组件。事实上,即使您确实为组件的克隆副本设置了唯一名称,您也无法通过该名称引用它,因为它是在运行时创建的。只有设计时组件可以通过其名称直接引用。

附带说明,记录可以(本质上)通过使用简单的:= 来复制,因为记录是值类型而不是类。但是,根据您的示例,我确信记录是不可能的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 2011-04-15
    相关资源
    最近更新 更多