How to determine the type of object?

Suppose I have a Treeview and it contains elements with Object pointers. How can I determine the object from the selected element, so I can access it?

Here is a basic example of some classes and code to give an idea: Note: TChildObject1 and TChildObject2 inherit from 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; 

Suppose they were created and added to TTreeview as follows:

 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; 

Now that I select Node in Treeview, how can I determine which class of Object a pointer leads to? I tried this that does not work:

Note. This is not an error, but it does not return the correct value (i.e. does not raise the correct object)

 procedure TForm1.TreeView1Click(Sender: TObject); var Obj: TMyObject; begin if TreeView1.Selected <> nil then begin Obj := TMyObject(TreeView1.Selected.Data); if Obj is TChildObject1 then begin Edit1.Text := 'this node is a child1 object'; end else if Obj is TChildObject2 then begin Edit1.Text := 'and this node is child 2 object'; end; end; end; 

I could do something like below, but I don’t think this is the right way, it means a lot of checking, declaring, appointing, etc.

 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; 

Hints and tips appreciated.

+4
source share
1 answer

The main problem is that you are freeing the memory of the object that you are adding to the tree structure. Thus, the node data indicates an invalid location.

To assign node objects, use code like this

  Obj := TChildObject1.Create(aName); aTreeView.Items.AddObject(nil, Obj.Name, Obj); 

and when you need to delete the data, you can call the Free method for each node.

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

Source: https://habr.com/ru/post/1384945/


All Articles