2

私の特定のクラスでは、オブジェクトの独立したコピーを返す関数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

したがって、正しいクラスが出てきました。この最小限の例では正しく動作しますが、残念ながら、必要な初期化は行われませんでした (2 回表示されるはずです)。

私はそれを明確にし、あなたが私のサンプルコードを気に入ってくれることを願っています:) -他のコメントや改善点も感謝します. 私のAssign()実装は大丈夫ですか?

4

2 に答える 2