1

さまざまな種類のクラスインスタンスのリストがあります。何を作成するかを確実に知らなくても、クラスの新しいインスタンスを作成できる必要があります。関連するすべてのオブジェクトは同じ祖先を持っています。オブジェクトのメンバー変数の実際のコピーは簡単です...問題があるのは新しいオブジェクトの作成です。

確かに私はこのようなことをすることができました:

case MyObjectTypeInstance.MyTypeEnum of
  obj1:
    Result:=TObjectType1.Create;

  obj2:
    Result:=TObjectType2.Create;

  obj3:
    Result:=TObjectType3.Create;
end;

それは「開放/閉鎖原則」に従わないでしょう。

最初は、「Result:=MyObjectTypeInstance.Create;」のようなことができると思いました。しかし、それはデストラクタの問題のために期待どおりに機能しませんでした。

これが私がこれをどのように行うべきかについての最新の推測です...

var
  fooA, fooB:TFoo;
begin
  fooA:=TFoo2.Create;    // it could be any of many types

  fooB:=?  // how to create fooB of same class type as fooA????

  // do something

  fooA.Free;
  fooB.Free;
end;

これはもっと簡単だと思いました!

ご協力ありがとうございました!

4

5 に答える 5

11

すべてのクラスに共通の祖先がある場合、次のようにすることができます。

type
  TAncestor = class;
  TAncestorClass = class of TAncestor;
  TAncestor = class 
  public
    constructor Create; virtual;

    class function CreateClass(const AId: string): TAncestor;
    class procedure RegisterClass(const AId: string; const AType: TAncestorClass);
  end;


class function TAncestor.CreateClass(const AId: string): TAncestor;
var
  atype : TAncestorClass;
begin
  atype := GetAncestorClass(AId);
  if atype<>nil then
    Result := atype.Create
  else
    Result := nil;
end;

class procedure TAncestor.RegisterClass(const AId: string; 
  const AType: TAncestorClass);
begin
  SetAncestorClass(AId, AType); // Link id to class type
end;

タイプの登録には、任意の種類の ID を使用できます。それらがユニークである限り。

于 2009-04-16T17:57:27.977 に答える
8

オプション 1 - 名前/クラス マッピングのリストを作成する: Delphi でクラスを名前でインスタンス化する方法はありますか?

オプション 2 - 「of class」変数を使用します。

type
  TBaseObj = class
  end;

  TObjA = class(TBaseObj)
  end;

  TBaseObjClass = class of TBaseObj;

var
  objCls: TBaseObjClass;
  obj: TBaseObj;

objCls := TObjA;
obj := objCls.Create;
//obj is of type TObjA
于 2009-04-16T17:56:55.140 に答える
4

おそらく、Abstract Factory または Factory Method クラスを作成したいと思うでしょう。これらは、テスト済みで実証済みの開発パラダイムである一般的なデザイン パターンです。

于 2009-04-16T19:29:58.677 に答える
2

別の厄介なバージョンは、「型のクラス」と TObject.ClassType を使用しています

type
 TFoo = class
  private
    { private declarations }
  public
    { public declarations }
    constructor Create(WhatEver : Integer);virtual;// just to show need for params
  end;

  TFooClass = class of TFoo;

  TFoo1 = class(TFoo)
  private
    { private declarations }
  public
    { public declarations }
    constructor Create(WhatEver : Integer);override;// just to show need for params
  end;

  TFoo2 = class(TFoo)
  private
    { private declarations }
  public
    { public declarations }
  end;


{$R *.dfm}

procedure TForm10.Button1Click(Sender: TObject);
var
  fooA, fooB:TFoo;

begin
  fooA:=TFoo2.Create(0);
  fooB:= TFooClass(FooA.ClassType).Create(1);

  // do something here

  fooA.Free;
  fooB.Free;

end;

{ TFoo }

constructor TFoo.Create(WhatEver: Integer);
begin
  ShowMessageFmt('%s %d', [Self.ClassName, WhatEver]);
end;

{ TFoo1 }

constructor TFoo1.Create(WhatEver: Integer);
begin
  inherited;

end;
于 2009-04-17T01:53:06.057 に答える
2

回答ありがとうございます。

dar7yl のソリューションは、私のニーズに完全に適合しました。

type
  TFoo = class
  private
    { private declarations }
  public
    { public declarations }
    class function MakeAnother:TFoo;
  end;

  TFoo1 = class(TFoo)
  private
    { private declarations }
  public
    { public declarations }
  end;

  TFoo2 = class(TFoo)
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  fooA, fooB:TFoo;
begin
  fooA:=TFoo2.Create;
  foob:=fooA.MakeAnother;

  // do something here

  fooA.Free;
  fooB.Free;
end;

{ TFoo }

class function TFoo.MakeAnother: TFoo;
begin
  Result:=Create;
end;
于 2009-04-16T19:57:43.647 に答える