Давайте посмотрим еще на одно, похожее чудо связанное с оператором is. Добавим к нашей группе проектов (ProjectGroup1) новый проект - DLL с именем AllMirrLib, в единственном модуле которого будет следующий код:
library AllMirrLib; uses Controls; function IsControlLib(const anObj: TObject): boolean; begin Result := anObj is TControl; end; exports IsControlLib; Figure 9. |
Как вы видите эта библиотека экспортирует только одну очень простую функцию, которая возвращает знечение True в том случае, если ее единственный параметр происходит от TControl и False - в остальных случаях.
В модуль формы нашего основного проекта добавим следующее определение:
unit AllMir;
interface ... implementation {$R *.DFM} function IsControlLib(const anObj: TObject): boolean; external 'AllMirrLib.DLL'; Figure 10. |
procedure TfrmAllMiracles.btnIsMrcl2Click(Sender: TObject); begin FControl := TControl.Create(nil); try if not IsControlLib(FControl) then ShowMessage('Not a Control'); finally FreeAndNil(FControl); end; end; Figure 11. |
Как вы уже наверное догадались FControl опять окажется не TControl. Найдите в модуле System процедуру _IsClass. Хоть она и написана на ассемблере, нетрудно понять, что в ней происходит - в цикле просматриваются ссылки на классы (сначала собственная - обьекта, а потом - всех предков) и среди них ищется равная правому операнду. Давайте изменим немного процедуру:
procedure TfrmAllMiracles.btnIsMrcl2Click(Sender: TObject); var p1, p2: pointer; begin FControl := TControl.Create(nil); try p1 := pointer(FControl.ClassType); p2 := pointer(TControl); if not IsControlLib(FControl) then ShowMessage('Not a Control'); finally FreeAndNil(FControl); end; end; Figure 12. |
Посмотрите под отладчиком значения p1 и p2 - они равны. Теперь изменим и функцию IsControlLib:
function IsControlLib(const anObj: TObject): boolean; var p3,p4: pointer; begin p3 := pointer(anObj.ClassType); p4 := pointer(TControl); Result := anObj is TControl; end; Figure 13. |
Да, кстати, не забудьте, что у вас два проекта в группе и компилируется всегда только активный проект. Так что не забывайте перпеключаться на нужный проект по мере необходимости или компилируйте сразу все: Alt-P, U.
Следующее чудо я встретил в программе одного начинающего программиста и оно было конечно слегка закамуфлировано, так что я, к своему стыду, даже не сразу понял в чем дело. Я видел значения переменных, знал, что это - переменные типа variant, но никак не мог понять почему результат вычисления некоего несложного выражения все время ошибочный. Проверьте себя и вы.