Delphi 如何识别对象类型?

Delphi 如何识别对象类型?,delphi,oop,pointers,Delphi,Oop,Pointers,假设我有一个树状视图,它包含带有对象指针的项。如何从所选项目确定对象是什么,以便访问它 下面是一些类和代码的基本示例,让我们了解一下: 注意:TChildObject1和TChildObject2继承自TMyObject type TMyObject = class private FName: string; public property Name: string read FName write FName; constructor Create(aN

假设我有一个树状视图,它包含带有对象指针的项。如何从所选项目确定对象是什么,以便访问它

下面是一些类和代码的基本示例,让我们了解一下: 注意:TChildObject1和TChildObject2继承自TMyObject

type
  TMyObject = class
  private
    FName: string;
  public
    property Name: string read FName write FName;

    constructor Create(aName: string);
  end;

type
  TChildObject1 = class(TMyObject)
  private
    FSomeString: string;
  public
    property SomeString: string read FSomeString write FSomeString;

    constructor Create(aName: string);
    destructor Destroy; override;
  end;

type
  TChildObject2 = class(TMyObject)
  private
    FSomeInteger: integer;
  public
    property SomeInteger: integer read FSomeInteger write FSomeInteger;

    constructor Create(aName: string);
    destructor Destroy; override;
  end;
假设它们是创建并添加到TTreeview的,如下所示:

procedure NewChild1(aTreeView: TTreeView; aName: string);
var
  Obj: TChildObject1;
begin
  Obj := TChildObject1.Create(aName);
  try
    aTreeView.Items.AddObject(nil, Obj.Name, Obj);
  finally
    Obj.Free;
  end;
end;

procedure NewChild2(aTreeView: TTreeView; aName: string);
var
  Obj: TChildObject2;
begin
  Obj := TChildObject2.Create(aName);
  try
    aTreeView.Items.AddObject(nil, Obj.Name, Obj);
  finally
    Obj.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // add the items to the tree
  NewChild1(TreeView1, 'Child Object 1');
  NewChild2(TreeView1, 'Child Object 2');
end;
现在,当我在树视图中选择一个节点时,如何确定指针指向哪个对象类?我试过这个,但不起作用:

注意:这不会出错,但不会返回正确的值(即,不会拾取正确的对象)

过程TForm1.treeview1单击(发送方:TObject);
变量
对象:TMyObject;
开始
如果TreeView1.选择了nil,则
开始
对象:=TMyObject(TreeView1.Selected.Data);
如果Obj是TChildObject1,则
开始
Edit1.Text:=“此节点是一个child1对象”;
结束其他
如果Obj是TChildObject2,则
开始
Edit1.Text:='且该节点为子2对象';
结束;
结束;
结束;
我可以像下面这样做,但我认为这不是正确的方法,它意味着大量的检查、声明、分配等

procedure TForm1.TreeView1Click(Sender: TObject);
var
  ChildObj1: TChildObject1;
  ChildObj2: TChildObject2;
begin
  if TreeView1.Selected <> nil then
  begin
    if TreeView1.Selected.Text = 'Child Object 1' then
    begin
      ChildObj1 := TreeView1.Selected.Data;    
      Edit1.Text := ChildObj1.SomeString;
    end else
    if TreeView1.Selected.Text = 'Child Object 2' then
    begin
      ChildObj2 := TreeView1.Selected.Data;  
      Edit1.Text := IntToStr(ChildObj2.SomeInteger);
    end;
  end;
end;
过程TForm1.treeview1单击(发送方:TObject);
变量
ChildObj1:TChildObject1;
ChildObj2:TChildObject2;
开始
如果TreeView1.选择了nil,则
开始
如果TreeView1.Selected.Text='Child Object 1',则
开始
ChildObj1:=TreeView1.Selected.Data;
Edit1.Text:=ChildObj1.SomeString;
结束其他
如果TreeView1.Selected.Text='Child Object 2',则
开始
ChildObj2:=TreeView1.Selected.Data;
Edit1.Text:=IntToStr(ChildObj2.SomeInteger);
结束;
结束;
结束;

感谢您的提示和建议。

主要问题是您正在释放要添加到treeview的对象的内存。因此,节点的数据指向无效位置

要将对象指定给节点,请使用如下代码

  Obj := TChildObject1.Create(aName);
  aTreeView.Items.AddObject(nil, Obj.Name, Obj);
当需要处理数据时,可以为每个节点调用
Free
方法

 for i:= 0 to TreeView1.Items.Count - 1 do
 begin
  Obj:= TMyObject(TreeView1.Items.Item[i].Data);
  if Assigned(Obj) then
   Obj.Free;
 end;

+1我正在学习OOP,出于某种原因,我认为我可以将Obj分配给所选的节点数据,但我想不会,我释放它太早了。刚刚编辑了我的代码,它现在识别了正确的对象:)@RRUZ:我将使用
TTreeView.OnDeletion
事件来释放对象,而不是使用循环,例如:
procedure TForm1.TreeView1删除(发送方:ToObject;节点:TTreeNode);开始对象(Node.Data).Free;结束
 for i:= 0 to TreeView1.Items.Count - 1 do
 begin
  Obj:= TMyObject(TreeView1.Items.Item[i].Data);
  if Assigned(Obj) then
   Obj.Free;
 end;