Как определить тип объекта? - PullRequest
4 голосов
/ 06 декабря 2011

Допустим, у меня есть древовидная структура, и она содержит элементы с указателями объектов.Как я могу определить из выбранного элемента, что такое Объект, чтобы я мог получить к нему доступ?

Вот базовый пример некоторых классов и кода, чтобы дать представление: Примечание: 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;

Теперь, когда я выбираю узел в древовидной структуре, как я могу определить, на какой класс объектов указатель указываетприводит к?Я пробовал это, которое не работает:

Примечание: это не ошибка, но это не возвращает правильное значение (то есть, не подбирает правильный объект)

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;

Я мог бы сделать что-то вроде ниже, но я не думаю, что это правильный путь, это означает много проверок, деклараций, назначений и т. Д.

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;

Советы и советы приветствуются.

1 Ответ

5 голосов
/ 06 декабря 2011

Основная проблема заключается в том, что вы освобождаете память объекта, который добавляете в древовидную структуру. Таким образом, данные узлов указывают на недопустимое местоположение.

Чтобы назначить объекты узлу, используйте код, подобный этому

  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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...