如何创建类的新实例?

发布于 2024-07-16 23:33:28 字数 732 浏览 3 评论 0原文

我有一个各种类实例的列表。 我需要能够在不知道要创建什么的情况下创建一个类的新实例。 所有涉及的对象都有相同的祖先。 对象的成员变量的实际复制很容易......这是我遇到问题的新对象的创建。

诚然,我可以做这样的事情:

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;

我本以为这会更容易!

感谢您的帮助!

i have a list of class instances of various kinds. i need to be able to create a new instance of a class without knowing for sure what to create. all the objects involved have the same ancestor. the actual copying of the object's member variables is easy...it's the creation of the new object where i have a problem.

admittedly i could do something like this:

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

  obj2:
    Result:=TObjectType2.Create;

  obj3:
    Result:=TObjectType3.Create;
end;

that wouldn't follow the "open/closed principle".

initially i thought i could do something like "Result:=MyObjectTypeInstance.Create;" but that didn't work as hoped because of destructor difficulties.

here's the latest guess how i should be doing this...

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;

i would've thought this'd be easier!

thank you for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

坦然微笑 2024-07-23 23:33:28

如果所有类都有一个共同的祖先,您可以这样做:

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;

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

If all classes have a common ancestor, you can do something like this:

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;

You can use any kind of identification for the type registration. As long as they are unique.

心如荒岛 2024-07-23 23:33:28

选项 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

Option 1 - create a list of name/class mappings: Is there a way to instantiate a class by its name in delphi?

Option 2 - use a 'of class' variable.

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
铁憨憨 2024-07-23 23:33:28

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

You will probably want to create an Abstract Factory or Factory Method class. These are common Design Patterns which are tested, proven development paradigms.

隱形的亼 2024-07-23 23:33:28

谢谢大家的答案!

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;

thank you all for your answers!

dar7yl's solution suited my needs perfectly.

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;
夜灵血窟げ 2024-07-23 23:33:28

另一个更混乱的版本是使用“类型的类”和 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;

Another, messier version is using "class of type" and 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文