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;

您可以使用任何类型的标识进行类型注册。只要它们是独一无二的。

于 2009-04-16T17:57:27.977 回答
8

选项 1 - 创建名称/类映射列表:有没有办法在 delphi 中通过其名称实例化一个类?

选项 2 - 使用“类”变量。

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

您可能想要创建一个抽象工厂或工厂方法类。这些是经过测试的、经过验证的开发范例的常见设计模式。

于 2009-04-16T19:29:58.677 回答
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 回答
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 回答