DelphiWin32 - 生成特定类的对象

发布于 2024-10-04 11:46:40 字数 229 浏览 3 评论 0原文

我正在使用 Delphi 2009。我有一个包含多个项目的 TListBox。我想为每个选定的项目生成特定类的对象。因此,如果用户选择项目编号 2 并单击“创建”按钮,则会创建特定类的对象。我想实现它只是检查当前所选项目的索引值,然后使用 if-then-else。或者我应该使用类引用,即对于每次单击项目我设置类引用的类型,然后在按钮的 OnClick 事件中创建对象?我想避免所有这些控件,只根据项目字符串的值创建对象。有什么想法吗?多谢!

I am using Delphi 2009. I have a TListBox with several items. I want to generate an object of specific class for each item selected. So if user select the item number 2 and click Create button an object of specific class is created. I was thinking to implement it just checking the index value of current item selected and then use if-then-else. Or should I use class reference i.e. for each click on item I set the type of class reference and then I create the object in OnClick event of button? I would like to avoid all these controls and just create the object basing on the value of item string. Any idea? Thanks a lot!

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

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

发布评论

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

评论(2

过期以后 2024-10-11 11:46:40

有几种选择。

简单索引

简单的解决方案是:

case ListBox1.ItemIndex of
  0 : temp := TApple.Create;
  1 : temp := TPineapple.Create;
  2 : temp := TGrape.Create;
else
  raise EFruitError.Create('Unknown fruit');
end;

很清楚,但是你必须在两个地方维护列表,这可能会导致错误。

类引用

假设所有水果都来自 TFruit,并具有虚拟构造函数。然后你可以这样做:

procedure TForm1.FormCreate(const Sender: TObject);
begin
  ListBox1.AddObject('Apple', TApple);
  ListBox1.AddObject('Pineapple', TPineapple);
  ListBox1.AddObject('Grape', TGrape);
end;

// Event handler:
procedure TForm1.CreateButtonClick(const Sender: TObject);
begin
  if ListBox1.ItemIndex>=0 then
    temp := TFruit(ListBox1.Items.Objects[ListBox1.ItemIndex]).Create;
end;

这有一个单点维护。这太棒了。

基于名称的参考
但是,如果您想根据列表中的名称创建对象,则可以创建某种工厂:

type
  TFruitClass = class of TFruit;
  TFruitFactory = class
  public
    class function CreateFruit(const AName: string): TFruit;
    class procedure RegisterFruit(const AName: string; const AFruitClass: TFruitClass);
  end;

工厂用于将类绑定到名称。每个类都使用名称进行注册。现在,您只需为工厂提供名称,工厂就会返回所需的类。

There are several options.

Simple Index

The simple solution is:

case ListBox1.ItemIndex of
  0 : temp := TApple.Create;
  1 : temp := TPineapple.Create;
  2 : temp := TGrape.Create;
else
  raise EFruitError.Create('Unknown fruit');
end;

Its clear, but you have to maintain the list at two places, which can lead to errors.

Class references

Assume all fruit descend from TFruit with a virtual constructor. Then you can do:

procedure TForm1.FormCreate(const Sender: TObject);
begin
  ListBox1.AddObject('Apple', TApple);
  ListBox1.AddObject('Pineapple', TPineapple);
  ListBox1.AddObject('Grape', TGrape);
end;

// Event handler:
procedure TForm1.CreateButtonClick(const Sender: TObject);
begin
  if ListBox1.ItemIndex>=0 then
    temp := TFruit(ListBox1.Items.Objects[ListBox1.ItemIndex]).Create;
end;

This has a single point of maintenance. Which is great.

Reference based on name
But if you want to create the objects based on a name in the list, you can create some kind of factory:

type
  TFruitClass = class of TFruit;
  TFruitFactory = class
  public
    class function CreateFruit(const AName: string): TFruit;
    class procedure RegisterFruit(const AName: string; const AFruitClass: TFruitClass);
  end;

The factory is used to bind classes to names. Each class is registered using a name. And now you just give the name to the factory and the factory returns the required class.

秋意浓 2024-10-11 11:46:40

要添加 Gamecat 的答案,您可以使用“classes.pas”中的类实用函数。下面的示例使用 GetClass 函数(并假设要创建的对象源自 TControl):

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.CommaText := 'TEdit,TButton,TPanel';
  RegisterClasses([TButton, TEdit, TPanel]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  pc: TPersistentClass;
  c: TControl;
begin
  if ListBox1.ItemIndex > -1 then begin
    pc := GetClass(ListBox1.Items[ListBox1.ItemIndex]);
    if Assigned(pc) then begin
      c := TControlClass(pc).Create(Self);
      c.Parent := Self;
    end;
  end;
end;

To add to Gamecat's answer, you can use class utility functions in 'classes.pas'. Below sample uses the GetClass function (and assumes objects to be created descend from TControl):

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.CommaText := 'TEdit,TButton,TPanel';
  RegisterClasses([TButton, TEdit, TPanel]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  pc: TPersistentClass;
  c: TControl;
begin
  if ListBox1.ItemIndex > -1 then begin
    pc := GetClass(ListBox1.Items[ListBox1.ItemIndex]);
    if Assigned(pc) then begin
      c := TControlClass(pc).Create(Self);
      c.Parent := Self;
    end;
  end;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文