Программирование - это просто
Advertisement
Главная arrow Уроки Delphi arrow Delphi изнутри arrow Delphi Изнутри. Урок 7. Продолжаем изучать TObject (ClassParent, Pointer, self).
19.04.2024 г.
Главное меню
Главная
Интернет магазин
Программные продукты
Биржевые роботы
Искусственный интеллект
Математика и информатика
1С:Предприятие
Уроки C#
Уроки Delphi
Уроки программирования
Web-программирование
Дизайн и графика
Компьютер для блондинок
Исходники
Статьи
Платный раздел
Рассказы про компьютеры
Хитрости и секреты
Системный подход
Размышления
Наука для чайников
Друзья сайта
Excel-это не сложно
Все о финансах
.
Delphi Изнутри. Урок 7. Продолжаем изучать TObject (ClassParent, Pointer, self). Печать E-mail
Автор megabax   
20.05.2010 г.
New Page 2

Delphi Изнутри. Урок 7. Продолжаем изучать TObject (ClassParent, Pointer, self).

Сегодня мы продвинемся в изучении TObject дальше и рассмотрим метод ClassParent. Если мы посмотрим объявление TObject, то увидим, что этот метод объявлен как классовый*:

Delphi Изнутри. Урок 7. Продолжаем изучать TObject (ClassParent, Pointer, self).

в чем, собственно говоря нет ничего удивительного, так как данная функция предназначена для определения родительского класса, а для этого нам не обязательно, что бы экземпляр класса хранился в памяти компьютера. Вот как реализован этот метод:

class function TObject.ClassParent: TClass;
{$IFDEF PUREPASCAL}
begin
    Pointer(Result) := PPointer(Integer(Self) + vmtParent)^;
    if Result <> nil then Pointer(Result) := PPointer(Result)^;
end;
{$ELSE}
asm
   MOV EAX,[EAX].vmtParent
   TEST EAX,EAX
   JE @@exit
   MOV EAX,[EAX]
   @@exit:
end;
{$ENDIF}

Как же работает данная функция? Сначала мы берем содержимое по адресу, смещенному на vmtParent от описания класса:

Pointer(Result) := PPointer(Integer(Self) + vmtParent)^;

Если это не nil, то мы берем содержимое ячейки, расположенной по этому адресу, а именно, ссылку на родительский класс. Если у нас класс не имеет родителя, например, тот же TObject, то метод вернет nil.

Где можно применить ClassParent? Например, для того, что бы проверить, является ли данный класс дочерним от заданного.  В качестве примера возьмем фрагмент кода библиотеки для создания компьютерных игр Easy Game Library:

function TEGBaseClass.IsChildOf(AName:String):Boolean;
var ClassRef: TClass;
begin
    ClassRef := ClassType;
    while ClassRef <> nil do
     begin
        if ClassRef.ClassName=AName then
        begin
            Result:=true;
            exit;
        end;
       ClassRef := ClassRef.ClassParent;
   end;
   Result:=false;
end;

Как работает данная функция? Она в цикле проверяет, равно ли имя класса предка имени заданного класса. Если да - значит, искомый класс потомок проверяемого. Если нет - проверяем уже родителя родителя. И так до тех пор, пока не дойдем до верхнего уровня.

Где применяется IsChildOf? Да в той же библиотеке, вот фрагмент кода:

procedure TEGPartsContainer.RedrawOwner;
var Image:TImage;
      LocationSize:integer;
      Axes:TEGAxesSystem;
begin
    if FOwner<>nil then
    begin
       if FOwner.IsChildOf('TEGLocationObject') then
       begin
          if FOwner.FOwner=nil then exit;
          if not(FOwner.FOwner.IsMap) then exit;
          Image:=TEGMap(FOwner.FOwner).Image;
          LocationSize:=TEGMap(FOwner.FOwner).LocationSize;
          Axes:=TEGMap(FOwner.FOwner).AxesSystem;
          TEGLocationObject(FOwner).DrawWithMap(Image,LocationSize,Axes);
       end;
   end;
end;

Объясняю какую роль здесь играет IsChildOf. Калсс TEGPartsContainer является контейнером составных частей объекта. Например, у объекта "стена" может быть составная часть"дверь" или "окно". У каждой составной части может быть владелец FOwner (у вышеназванной "двери" или "окна" это будет "стена"). В тот момент, когда нам надо перерисовать объект (например, дверь сменила состояние из "закрыта" в "открыта"), мы не знаем, можно ли владельца объекта перерисовать. Если да, то мы и перерисовываем его, с учетом новых состояний частей объекта. Если нет - ничего не делаем.

 


Скриншоты, помеченные знаком * , являются цитатами и иллюстрациями  программного продукта "Delphi", авторское право на который принадлежит "Borland Software Corporation".


Последнее обновление ( 05.06.2013 г. )
 
« След.   Пред. »
 
© 2024 Программирование - это просто
Joomla! - свободное программное обеспечение, распространяемое по лицензии GNU/GPL.
Русская локализация © 2005-2008 Joom.Ru - Русский Дом Joomla!
Design by Mamboteam.com | Powered by Mambobanner.de
Я принимаю Яндекс.Деньги