在我的特定TPersistent
类中,我想提供一个Clone
函数,它返回对象的独立副本。
是否可以在后代中正常工作,而无需Clone
在每个后代中实现该功能?
这与克隆任何未知字段或深度克隆(可以使用 RTTI 完成)无关。在下面我的最小示例中,您可以看到我想要放置Clone
函数的位置。
由于它用于Assign()
复制数据,因此它适用于任何后代。问题是构造函数,请参阅评论。如何调用该后代的正确构造函数?如果这很难做到,可以假设没有一个后代在没有覆盖的情况下覆盖构造函数Clone
。
program Test;
uses System.SysUtils, System.Classes;
type
TMyClassBase = class abstract(TPersistent)
public
constructor Create; virtual; abstract;
function Clone: TMyClassBase; virtual; abstract;
end;
TMyClassBase<T> = class abstract(TMyClassBase)
private
FValue: T;
public
constructor Create; overload; override;
function Clone: TMyClassBase; override;
procedure Assign(Source: TPersistent); override;
property Value: T read FValue write FValue;
end;
TMyClassInt = class(TMyClassBase<Integer>)
public
function ToString: string; override;
end;
TMyClassStr = class(TMyClassBase<string>)
public
function ToString: string; override;
end;
constructor TMyClassBase<T>.Create;
begin
Writeln('some necessary initialization');
end;
procedure TMyClassBase<T>.Assign(Source: TPersistent);
begin
if Source is TMyClassBase<T> then FValue:= (Source as TMyClassBase<T>).FValue
else inherited;
end;
function TMyClassBase<T>.Clone: TMyClassBase;
begin
{the following works, but it calls TObject.Create!}
Result:= ClassType.Create as TMyClassBase<T>;
Result.Assign(Self);
end;
function TMyClassInt.ToString: string;
begin
Result:= FValue.ToString;
end;
function TMyClassStr.ToString: string;
begin
Result:= FValue;
end;
var
ObjInt: TMyClassInt;
ObjBase: TMyClassBase;
begin
ObjInt:= TMyClassInt.Create;
ObjInt.Value:= 42;
ObjBase:= ObjInt.Clone;
Writeln(ObjBase.ToString);
Readln;
ObjInt.Free;
ObjBase.Free;
end.
输出是
some necessary initialization
42
所以,正确的类出来了,它在这个最小的例子中正常工作,但不幸的是,我必要的初始化没有完成(应该出现两次)。
我希望我能说清楚,你喜欢我的示例代码:) - 我也很感激任何其他评论或改进。我的Assign()
实施好吗?