.
Delphi Изнутри. Урок 9. Класс TObject. Функция InheritsFrom
Автор megabax   
29.06.2010 г.
New Page 2

Delphi Изнутри. Урок 9. Класс TObject. Функция InheritsFrom

Продолжаем копаться во внутренностях TObject. Добрались до InheritsFrom. Данный метод проверяет порожден ли объект от объекта другого типа. Рассмотрим пример использования:

procedure TfrmTetsInheritsFrom.btnTestClick(Sender: TObject);
begin
      if (Sender.InheritsFrom(TWinControl)) then
                       frmTetsInheritsFrom.Caption := 'TButton descends from TWinControl';
end;

При нажатии на кнопочку с таким обработчиком заголовок форму превратиться в TButton descends from TWinControl:

Delphi Изнутри. Урок 9. Класс TObject. Функция InheritsFrom

Если мы поставим вместо TWinControl, например, TEdit, то при нажатии на кнопку ничего не произойдет, так как TButton у нас не является дочерним классом от TEdit. А если поставить TButton? Давайте проверим

procedure TfrmTetsInheritsFrom.btnTestClick(Sender: TObject);
begin
      if (Sender.InheritsFrom(TButton)) then
             frmTetsInheritsFrom.Caption := 'TButton descends from TButton';
end;

вот что у нас получилось:

Delphi Изнутри. Урок 9. Класс TObject. Функция InheritsFrom

Теперь посмотрим, как же реализован этот метод:

class function TObject.InheritsFrom(AClass: TClass): Boolean;
{$IFDEF PUREPASCAL}
var
   ClassPtr: TClass;
begin
    ClassPtr := Self;
    while (ClassPtr <> nil) and (ClassPtr <> AClass) do
         ClassPtr := PPointer(Integer(ClassPtr) + vmtParent)^;
    Result := ClassPtr = AClass;
end;
{$ELSE}
asm
{ -> EAX Pointer to our class }
{ EDX Pointer to AClass }
{ <- AL Boolean result }
   JMP @@haveVMT
   @@loop:
   MOV EAX,[EAX]
   @@haveVMT:
   CMP EAX,EDX
   JE @@success
   MOV EAX,[EAX].vmtParent
   TEST EAX,EAX
   JNE @@loop
   JMP @@exit
   @@success:
   MOV AL,1
   @@exit:
end;
{$ENDIF}

Работает этот метод аналогично тому, как реализованный в библиотеке для создания компьютерных игр Easy Game Library метод IsChildOf, об этом я рассказывал в уроке 7. Иными словами, в цикле происходит сравнение заданного класса с текущим. Сначала текущий класс равен самому классу объекта, затем, на каждой итерации берется родительский класс от текущего. И так до тех пор, пока не будет найдено совпадение или не дойдет до вершины иерархии классов. В последнем случае функция вернет false - данный класс не наследуется от заданного.

- В чем же разница между InheritsFrom и IsChildOf? - спросите вы.

- В том, что в последнем задается имя класса строкой,  - отвечу я, - тоесть, по сути дела, пользователь может его ввести с клавиатуры.

Последнее обновление ( 05.06.2013 г. )