正确的方法来复制Delphi对象 [英] Correct way to duplicate Delphi object

查看:1389
本文介绍了正确的方法来复制Delphi对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用构造函数或实例函数复制对象实例的优点和缺点是什么?

What are pros and cons of duplication an object instance with constructor or instance function?

示例A:

type
  TMyObject = class
  strict private
    FField: integer; 
  public
    constructor Create(srcObj: TMyObject); overload; 
    //alternatively:
    //constructor CreateFrom(srcObj: TMyObject);
    property Field: integer read FField;
  end;

constructor TMyObject.Create(srcObj: TMyObject);
begin
  inherited Create;
  FField := srcObj.Field;
end;

示例B:

type
  TMyObject = class
  strict private
    FField: integer; 
  public
    function Clone: TMyObject;
    property Field: integer read FField;
  end;

function TMyObject.Clone: TMyObject;
begin
  Result := TMyObject.Create;
  Result.FField := FField;
end;

一个主要的区别立刻就会消失,在后一种情况下,Create构造函数必须是虚拟的一个支持Clone的类层次结构可以建立在TMyObject的基础上。

One major difference immediately springs to mind - in the latter case the Create constructor would have to be virtual so that a class hierarchy supporting Clone could be built basing on the TMyObject.

假设这不是问题 - TMyObject和基于它的一切完全在我的控制之下。你在Delphi中做拷贝构造函数的首选方法是什么?你觉得哪个版本更容易阅读?你什么时候使用前者或后者的方法?讨论。 :)

Assume that this is not a problem - that TMyObject and everything based on it is entirely under my control. What is your preferred way of doing copy constructor in Delphi? Which version do you find more readable? When would you use former or latter approach? Discuss. :)

编辑:
我的主要关注的第一个例子是,与第二种方法相比,使用非常重,例如

My main concern with the first example is that the usage is very heavy compared to the second approach, i.e.

newObj := TMyObject.Create(oldObj)


b $ b

vs。

vs.

newObj := oldObj.Clone;

EDIT2或为什么我要单行操作

EDIT2 or "Why I want single-line operation"

我同意Assign在大多数情况下是合理的方法。通过简单地使用assign,在内部实现复制构造函数甚至是合理的。

I agree that Assign is a reasonable approach in most cases. It's even reasonable to implement 'copy constructor' internally by simply using assign.

我通常在多线程和通过消息队列传递对象时创建这样的副本。如果对象创建速度很快,我通常会传递原始对象的副本,因为这真的简化了对象所有权的问题。

I'm usually creating such copies when multithreading and passing objects through the message queue. If object creation is fast, I usually pass a copy of the original object because that really simplifies the issues of object ownership.

IOW,我更喜欢写

Send(TMyObject.Create(obj));

Send(obj.Clone);

newObj := TMyObject.Create;
newObj.Assign(obj);
Send(newObj);


推荐答案

第一个添加有关要创建的对象的信息,第二个不是。这可以用于实例化例如。

The first adds information about which object to want to create, the second not. This can be used to instantiate e.g. a descendant or an ancestor of a class

Delphi方法( TPersistent )分隔创建和克隆:

The Delphi way (TPersistent) separates creation and cloning:

dest := TSomeClass.Create; 
dest.Assign(source);  

,并且具有与显式选择要实例化的类相同的属性。但是你不需要两个构造函数,一个用于正常使用,另一个要克隆。

and has this same property that you explicitly choose the class to instantiate. But you don't need two constructors, one for normal use, and one where you want to clone.

由于online需求而编辑
当然可以使用Delphi元类(未测试)混合它

edit due to oneline requirement You can mix it of course using Delphi metaclasses (untested)

type
  TBaseSomeObject = class;
  TBaseObjectClass = class of TBaseSomeObject;

  TBaseSomeObject = class(TPersistent)
    function Clone(t: TBaseObjectClass = nil): TBaseSomeObject; virtual;
  end;

...

  function TBaseSomeObject.Clone(t: TBaseObjectClass = nil): TBaseSomeObject;
  begin
    if Assigned(t) then
      Result := t.Create
    else
      Result := TBaseObjectClass(Self.ClassType).Create;
    Result.Assign(Self);
  end;


 SendObject(obj.Clone); // full clone.
 SendObject(obj.Clone(TDescandantObject)); // Cloned into Descendant object 

对于其余的,只需实现 assign )运算符,并且您可以混合多种方式。

For the rest, just implement your assign() operators, and you can mix multiple ways.

edit2

我用D2009中测试的代码替换了上面的代码。有一些依赖的类型可能会困惑你,希望这是更清楚这种方式。当然,你必须学习分配机制。我也测试了 metaclass = nil 默认参数,它的工作原理,所以我添加了它。

I replaced the code above with code tested in D2009. There are some dependencies of the types that might have confused you, hope it is clearer this way. Of course you'll have to study the assign mechanism. I also tested the metaclass=nil default parameter and it works, so I added it.

这篇关于正确的方法来复制Delphi对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆