With TButton.Create(Sell) Do Begin
Parent:=Self; // Указывать Fonnl не требуется
SetBounds(X,Y,W,H); // (X- Left, Y- Top. W- Width, H - Height)
Name:='NewButton'; // Caption также будет равно NewButton
Visible:=True;
. . . // Значения других свойств
End;
Поскольку классовые методы могут вызываться и при отсутствии экземпляров класса, то они не могут иметь доступ к полям класса, поэтому у них отсутствует встроенный Self, и нет возможности использовать его поля, поэтому для классовых методов Self - переменная типа ссылки на класс, чей классовый метод был вызван. Фактически Self для классовых методов указывает на VMT.
ВИДИМОСТЬ КОМПОНЕНТОВ КЛАССА
Одно из больших преимуществ ООП - это инкапсуляция и ее поддержка для скрытия данных. Если работать с полями напрямую или просто показывать их, в результате детали реализации становятся известными и могут не всегда корректно взаимодействовать с внешним миром. Гораздо лучше написать методы для доступа к полям объекта, что позволит добиться настоящей инкапсуляции и исключит возможность некорректной модификации данных объектов. Вместо прямого доступа к полям вызываются соответствующие методы. Основные достоинства такого доступа к полям следующие:
• Надежность данных. Вы можете предотвратить изменения компонента данных, выполнив в методе дополнительную проверку значения на допустимость. Тем самым можно гарантировать, что экземпляр всегда будет "исправен".
• Целостность ссылок. Перед доступом к объекту, связанному с вашим, вы можете удостовериться, что косвенное поле содержит корректное значение. Если это не так, например экземпляр уже отсутствует, то можно инициировать исправление положения, например, заново создать отсутствующий экземпляр.
• Предусмотренные побочные эффекты. Вы можете гарантировать, что каждый раз, когда выполняется обращение к полю объекта, синхронно с ним выполняется какое-либо специальное действие. Например, можно подсчитывать число обращений к экземпляру для целей статистики, для расчета суммы оплаты, ограничения доступа и т.п.
• Скрытие информации. Когда доступ к данным осуществляется только через методы, вы можете скрыть детали реализации объекта, а для изменения реализации вам будет необходимо изменить лишь методы доступа к полям. Те части программы, которые использовали ваш класс не будут затронуты.
Техника скрытия информации с помощью методов (отказ от прямого доступа к полям) одна из базовых концепций ООП и называется разграничением информации (information hiding). Удаляя ненужные внутренние детали из рассмотрения, это техника помогает сконцентрироваться на построении архитектуры своей системы на настоящем уровне абстракции.
Как уже упоминалось, ОР определяет несколько стандартных ключевых слов, называемых директивами, которые изменяют видимость компонентов, объявленных внутри описания класса. Для обеспечения различной видимости компонентов определение класса может быть разделено на несколько разделов с разной степенью видимости или доступности, включенных в них компонентов. Каждый раздел может начинаться с одной из директив:Private,
Protected, Public, Published.
Первый раздел по умолчанию, когда объявление класса не содержит разделов или до появления первой директивы видимости, считается разделом
Public.
Синтаксис разделения определения класса на разделы следующий:
Type
<имя класca>=Class[(<имя родительского класса>}]
Private // Внутренние детали реализации класса
<частные поля и методы>
Protected // Интерфейс разработчика
<защищенные поля и методы>
Public // Run-time интерфейс
<публичные поля и методы>
Published // Design-time интерфейс
<опубликованные поля и методы>
End;
Особенности указанных разделов следующие:
• Private (частный). Означает высший уровень ограниченности видимости компонентов класса. Компоненты видны только в пределах модуля, в котором виден этот класс. Таким образом, другое классы и другие переменные могут видеть компоненты этого раздела только внутри этого модуля. Обычно в этот раздел помещают поля и методы, оказывающие решающее воздействие на поведение объектов и их неосторожная модификация может привести к непредсказуемым последствиям.
• Protected (защищенный). Означает частично ограниченную видимость компонентов класса. Доступ возможен через методы класса и, кроме того, компоненты видны внутри потомков этого класса, в том числе и в других модулях. Если потомки не объявлены, то поля и методы этого раздела аналогичны разделу Private.
• Public (публичный). Означает полную видимость. Компоненты этого раздела класса видны всюду, где виден сам класс. Вместо полей Public часто используются свойства.
• Published (опубликованный). Компоненты этого класса не только доступны, как и компоненты Public, но они имеют специальную информацию для Инспектора объектов Delphi. Для полей и методов этого раздела порождается информация о типах времени выполнения (RTTI). Во время выполнения программы компоненты, объявленные в разделах Public и Published, ведут себя одинаково, однако информацию о компонентах из раздела Published можно получить из внешней программы.
На компоненты из этого раздела, накладываются ограничения:
• Любое поле в этом разделе должно иметь тип класса или интерфейса.
• Свойства, объявляемые в этом разделе, могут иметь порядковый, действительный (кроме Real48), строковый, тип класса или интерфейса, малого множества (ограничен значениями 0..31) или указателя на метод (но не глобальный процедурный тип).
• Класс может иметь этот раздел, если он генерируется с командой генерации информации о типах времени выполнения (команда компилятору задается ключом $М+, иначе будет раздел Public) или является наследником этого класса.
• Чаще всего этот раздел не содержит ни полей, ни методов. В ней находятся свойства.
Хороший стиль программирования предполагает, чтобы все поля относились к разделу Private, а методы - к Public.
Фактически есть еще один раздел - Automated, используемый для создания объектов автоматизации при использовании технологии СОМ.
НАСЛЕДОВАНИЕ
Основные понятия
Классы могут быть связаны между собой различными способами. Одна из фундаментальных концепций ООП - это понятие наследования классов, устанавливающее между двумя классами отношения "родитель-потомок".
Наследование (субклассирование) - это способность одного класса использовать характеристики другого. Оно использует отношение "вид чего-либо" между двумя классами. Этот простой принцип означает, что если вы хотите создать новый класс, лишь немного отличающийся от известного, то нет необходимости в переписывании заново полей и методов уже существующих у класса-предка.
Предок (ancestor) - это класс, представляющий свои возможности и характеристики другим классам через механизм наследования.
Класс, который использует характеристики другого класса посредством наследования, называется егопотомком (descendant).
Непосредственный предок, от которого данный класс прямо происходит, называетсяродителем (parent).
Примечания:
• ОР поддерживает модель наследования, известную как простое наследование, которое ограничивает число родителей конкретного класса одним. Другими словами, пользовательский класс может иметь только одного родителя.
• Особенностью наследования является то, что:
• оно расширяет возможности в том смысле, что любой класс-потомок имеет доступ или наследует практически все ресурсы (методы, поля и свойства) родительского класса и всех его предков до самого верхнего уровня иерархии, т.е. до класса TObject. Наследование поддерживает повторное использование кода у потомков;
• наследование позволяет потомку усовершенствовать родительский класс, сделав его более специализированным. В определении класса-потомка указываются лишь новые методы, замещающие методы и новые поля.
• В классах-потомках можно переносить объявления из одного раздела в другой, с большей видимостью, кроме раздела Private, из которого в разделы с большей видимостью не переносят.
• Следует выбирать родительский класс таким образом, чтобы основное соотношение "вид чего-либо" соблюдалось. Например, нельзя сказать "Принтер - это вид дисплея", но можно сказать "Принтер - это вид выходного устройства ".
Наследование полей
Примечания:
• Поля, унаследованные от класса-родителя, располагаются перед новыми.
• В классе-потомке можно заместить наследуемый метод, но нельзя отказаться от наследования какого-либо поля.
• В классе-потомке можно объявить одноименное поле другого типа и этим скрыть прямой доступ к переопределенному полю. Тем не менее доступ будет возможен к обоим полям:
• к новому - напрямую:
ОЬ/.<поле>;
• к переопределенному - используя приведение типов (typecast):
TParentClass(Obj). <поле>;
• При переопределении поля можно перенести его объявление в раздел класса с другой видимостью, однако нельзя перенести объявления полей из раздела Private.
4.3. Поведение методов при наследовании
По тому, какие действия происходят при вызове, методы делятся на четыре группы: Static (статические). Virtual (виртуальные). Dynamic (динамические), Abstract (абстрактные). Одной из проблем наследования является диспетчеризация вызовов методов объектов, под которой понимается то, каким образом приложение будет определять какой код требуется выполнить при вызове того или иного метода. Во многом это определяется видом метода.
а) Статические методы.
По умолчанию все методы класса являются статическими. Транслятор разрешает вызовы статических методов на фазе трансляции. К моменту запуска программы адреса вызова статических методов уже известны и, поэтому они вызываются быстрее других. Этот механизм называют еще ранним связыванием (early binding).
Примечания:
• Статический метод можноскрыть, если определить новый виртуальный или динамический метод с тем же именем.
• Статический метод можнопереопределить, если в наследуемом классе объявить новый статический метод с тем же именем. Можно изменять при переопределении и список параметров.
• Доступ к скрытому или переопределенному статическому методу возможен с помощью механизма приведения типов:
TParentClass(Obj). <метод>;
• Вызов статического метода определяется исключительно типом объектной переменной. Тип самого объекта, на который эта переменная в данный момент ссылается, не имеет значения, т.е. при вызове статического метода фактический класс объекта игнорируется1'.
б) Виртуальные методы.
Принципиально от статических отличаются вызовы виртуальных и динамических методов. Адреса этих методов определяются лишь во время выполнения программы из специальной таблицы. Такой поиск называют еще поздним связыванием (late binding). Решение о вызове конкретного метода решается в процессе выполнения программы, и решение основывается на данных, хранящихся в объекте, вызывающем метод. Таким образом, появляется возможность реализовать различные варианты поведения объектов разных классов при вызове методов с одним именем. Это, по сути, определение полиморфизма.
Когда компилятор встречает обращение к виртуальному методу, он подставляет вместо обращения к конкретному адресу код-смещение относительно начала специальной таблицы, из который и извлекается нужный адрес. Эта таблица называется таблицей виртуальных методов (Virtual Method Table, VMT). Такая таблица есть у каждого класса. В ней хранятся указатели (адреса) всех виртуальных методов класса: вновь объявленных и унаследованных. Отсюда достоинства и недостатки: они вызываются сравнительно быстро, хотя и медленнее статических, однако для хранения указателей требуется большее количество памяти. Так, если в базовом классе 5 виртуальных методов и у этого класса 5 производных классов, то фактически будет 30 указателей, содержащих почти идентичную информацию, которые займут 120 байт памяти в куче (Heap).
Доступ к виртуальному методу через VMT - это извлечение адреса по коду (смещению) из таблицы, состоящее из одной машинной инструкции.
Примечания:
• Для объявления метода виртуальным служит ключевое слово-директиваVirtual, которое указывается в конце объявления заголовка метода после точки с запятой.
• ДирективаVirtual всегда вводит новый виртуальный метод, никак не
' Если в программе встречается обращение Obj.StaticMethod, гдеObj - переменнаяTClassType, то генерируется вызов методаTCIassType.StaticMethod или ближайший StaticMethod, наследуемый классом TCIauType. ПеременнаяObj может ссылаться на один из потомков класса, производного отTClassType, в котором определен свойStaticMethod, т.е. фактически будет использоваться экземпляр дочернего класса. Тем не менее будет вызван именноTClassType.StaticMethod, т.е. для дочернего класса будет вызываться метод родителя связанный с любым другим одноименным методом, наследуемым классом. Переопределенный виртуальный метод ведет себя аналогично переопределенному статическому методу, т.е. полиморфизм не проявляется. Переопределить виртуальный метод в потомке можно и статическим методом.
Type T1=Class
Procedure Test; Virtual;
End;
T2=Class(T1)
Procedure Test; // Test скрывается, но не замещается
End;
Var SomeObject: T1;
Begin
SomeObject:=T2.Create;
SomeObject.Test; // Вызывается T1.Test
• У каждого производного класса свое пространство имен, предваряющее пространство имен всех наследуемых этим классом методов. Поэтому можно скрыть наследуемый метод, объявив одноименный виртуальный метод. Однако в VMT таблице сохраняется адрес нового и старого (переопределенного) виртуального метода, следовательно, к переопределенному виртуальному методу возможен доступ с использованием механизма приведения типов:
TParentClass(Obj). <метод>;
Синтаксис объявления виртуальных методов:
Procedure|Constructor|Destructor <имя метода>[(<параметры>)};
Virtual;
Function <имя метода>[(<параметры>)]: <тип результатам>;Virtual;
в) Динамические методы.
Динамические методы вызываются медленнее виртуальных, но позволяют более экономно расходовать память. Каждому динамическому методу присваивается индекс - отрицательное число. В таблице динамических методов (Dynamic Method Table, DMT) класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе. Если в DMT данного класса адрес нужного динамического метода не находится, то просматривается DMT класса-предка, и так далее по всей цепочке наследования до класса TObject. Таким образом, доступ к методу через DMT может привести к активному поиску в DMT разных классов и потребовать сотен тактов процессора.
Во всем остальном между виртуальными и динамическими методами нет принципиальной разницы. Там, где можно использовать виртуальный метод, там можно использовать и динамический, но с меньшими затратами памяти и быстродействием. Динамические методы используются для редко вызываемых методов, когда потерями в производительности можно пренебречь. Синтаксис объявления динамических методов:
Proctdure <имя метода>[(<параметры>)};Dynamic;
Function <имя метода>[(<параметры>)}: <тип результата>;Т>упят.1С;
Редко перекрываемые методы рекомендуется делать динамическими.
г) Замещающие методы.
В то время как, директивы Virtual и Dynamic всегда вводят новое имя метода, то директива Override всегда указывает на новую реализацию уже существующего наследуемого виртуального или динамического метода. Весь смысл виртуальных и динамических методов состоит в том, чтобы дать классу-потомку возможность модифицировать поведение метода, введенного в его классе-предшественнике. Директива Override служит для того, чтобы дать понять транслятору, что ваша цель - модифицировать (заменить или расширить - два разных варианта) реализацию наследуемого метода.
Объявление Override-метода должно в точности совпадать с объявлением исходного Virtual или Dynamic метода по названию, числу, именам и типам параметров, а также типу результата для функции. Новая строка в VMT (DMT) таблице не создается, поскольку адрес замещенного метода записывается в строку таблицы замещаемого метода. Таки" образом, у класса-предка и класса-потомка адрес одноименного метода находится в строке таблицы VMT (DMT) с одинаковым смещением от ее начала. Однако "начинка" этих методов различна.
Синтаксис объявления замещающих виртуальных методов:
Procedure|Constructor|Destructor <имя метода>[(<параметры>)];Override;
Function <имя метода>[{<параметры>)]: <тип результата>;Override;;
Если в одноименных статических методах производных классов списки параметров могут различаться, то список параметров виртуального метода нельзя изменять при замещении в производном классе. Это объясняется тем, что нет никакой связи между одноименными статическими методами производных классов, и есть сильная связь между одноименными виртуальными методами. Так вызов виртуального метода может во время работы программы привести к вызову любой из его реализации (принцип полиморфизма) в производных классах, поэтому у них у всех должны быть идентичные списки параметров.
д) Абстрактные методы.
Абстрактными называются методы, которые определены в классе, но не содержат его реализации в этом классе. Они никогда не вызываются в объявленном классе и должны быть переопределены и реализованы в его наслед никах. Абстрактными могут быть только виртуальные и динамические методы. Их основное назначение, - абстрагируясь от частностей, быть родоначальниками иерархии конкретных методов в классах наследниках. Такие методы лежат в основе принципа полиморфизма. Для объявления метода абстрактным используется слово-директива Abstract, которое указывается после слова-директивы Virtual (Dynamic). Эта директива действительна лишь при первом объявлении метода класса. Если абстрактный метод в наследниках оказался неопределенным, то его вызов генерирует ошибку или исключительную ситуацию.
Синтаксис объявления абстрактных методов:
Procedure <имя метода>[(<параметры>)];Virtual; Abstract;
Function <имя метода>[(<параметры>)]: <тип результата>;
Virtual; Abstract;
Procedure <имя метода>[(<параметры>)];Dynamic; Abstract;
Function <имя метода>[(<параметры>)]: <тип результата>;
Dynamic; Abstract;
В VMT (DMT) для абстрактного метода резервируется строка, в которую вместо адреса вызова метода заносится Nil.
В общем контексте под виртуальными методами понимают как собственно виртуальные методы, так и динамические методы или Override-методы (замещаемые).
Таким образом, у каждого классового типа имеется своя уникальная VMT. Блок данных экземпляра класса, в свою очередь, содержит скрытый указатель на VMT своего классового типа. Когда транслятору необходимо сгенерировать код для вызова виртуального метода, он сначала генерирует код для получения указателя на VMT из данных экземпляра класса (первого поля), затем получает адрес кода нужного метода из соответствующего поля VMT, после чего выполняет вызов по полученному адресу. Реально на все это требуется две машинные инструкции.
Примечание:
• Объявления методов, как и полей можно переносить из одного раздела в другой. Невозможно только переносить объявления из раздела Private в раздел с большей видимостью.
е) Повторное объявление методов (перегрузка методов).
Повторное объявление обычных процедур и функций, а также методов позволяет создавать подпрограммы с одинаковыми именами, но с несколько различными возможностями. Исторически перегрузка впервые была введена в C++ для того, чтобы позволить использование нескольких конструкторов с одинаковым именем (именем класса). В ОР эта возможность не считалась необходимой просто потому, что здесь можно объявлять конструкторы с разными именами. Однако из-за интеграции Delphi и C++ Builder фирма Borland пошла на введение этой особенности в ОР.
Перегрузка нужна для того, чтобы произвести одинаковые или похожие действия с разнотипными данными. Виртуальными их сделать нельзя, поскольку тогда тип и число параметров должны совпадать.
Для указания компилятору о tqm, что подпрограммы, включая конструкторы и статические методы, имеют одинаковые имена, используется слово-директиваOverload у каждой из них, при объявлении в одном классе или у предка и потомка. Подпрограммы, объявленные с директивой Overload, должны различаться или числом или типом параметров (тип результата функции не является различием). Оба перегружаемых метода доступны, даже если второй определен в классе-наследнике, поскольку компилятор определит различие в параметрах.
Есть два ограничения на перегрузку методов:
• нельзя дважды перегружать методы в разделе Published одного и того же класса;
• для объявления виртуального метода перегружаемым в классе-наследнике дополнительно добавляется слово-директиваReintroduce.Синтаксис применения директивы Reintroduce:
Procedure <имя метода>[(<параметры>)];Reintroduce; Overload;
Type T1=Class
Procedure Test(I: Integer); Overload; Virtual;
End;
// В бачовом классе не обязательно помечать метод как Overload
T2=Class(T1)
Procedure Test(S: String); Reintroduce; Overload;
End;
Begin
SomeObject:=T2.Create;
SonieObject.Test('HeIlo'); // Фактически вызывается Т2.Test
SomeObject.Test(7); // Фактически вызывается Т1.Test
Tl(SomeObject).Test(7); // Можно и так, если известно имя – Т1
По отношению к методам перегрузка позволяет упростить доступ к одноименным методам родительского класса, не зная имя класса с одноименным методом.
ж) Дружественные классы.
В языке C++ с помощью ключевого словаfriend реализуется концепция дружественных классов, т.е. классов, объектам которых разрешен доступ к Private полям и методам другого класса. В ОР подобного слова нет, однако объекты классов, описанных в одном модуле, имеют взаимный доступ ко всем разделам объектов другого класса. Таким образом фактически реализуется дружественность классов в Delphi.
Иерархия классов
По мере добавления свойств и методов классы становятся все более специализированными. Начало иерархии классов Delphi, взятое из справочной системы, приведено на следующем рисунке.
Последовательность добавления особенностей в классы можно проследить на примере визуального класса, реализующего кнопки управления. Эта иерархия классов представлена на следующем рисунке.
На каждом уровне иерархии добавляются важные возможности для класса:
• TObiect - Включает более 25 методов, общих для всех объектов (17 Delphi 1).
» TPersistent - Добавляет возможность писать самого себя в ЕХЕ файл во время компиляции и переносить себя обратно из ЕХЕ файла во время выполнения.
• TComponent - Вводит имя компонента (Name), множество состояний объекта (чтение, запись, выборка и т.п.), указатель на владельца (Owner), обеспечивает возможность создания компонентов во время выполнения программы с соответствующей регистрацией компонентов в списке.
• TControl - Добавляет возможность взаимодействия с пользователем.
• TWinControl - Добавляет возможность использовать механизмы Windows для создания окон.
• TButtonControl - Обеспечивает работу с кнопками.
• TButton - Реализует "реальные" кнопки с конкретными возможностями: изменение поверхности, опускание кнопки и т.п.
RTTI
Переменная типа класса представляет собой 4-х байтный указатель на экземпляр класса, который и является объектом. Внутренний формат данных объекта похож на запись. Каждый экземпляр класса содержит отдельную копию его полей. Поля, как уже указывалось, располагаются в порядке объявления, начиная с предков. Рассмотрим внутреннюю структуру объекта, которая приведена на следующем рисунке.
• Первое поле каждого экземпляра класса хранит указатель на свой класс, точнее на начало специальной 76-байтной структуры (Delphi 5), называемойRTTI (Run-Time Type Information) - генерируемой транслятором описание класса, содержащее информацию времени выполнения о типе. RTTI предоставляет приложениям Delphi возможность получения информации об объектах непосредственно во время выполнения программы. Формат RTTI -это запись, поля которой приведены в табл.1. В RTTI содержатся данные, полностью характеризующие класс, а класс TObject включает несколько методов, предназначенных для получения информации о конкретном экземпляре объекта: его имя (ClassName), размер экземпляра (InstanceSize), указатели на класс-предок (ClassParent), тип класса (ClassType) т.п. Одно из полей (со смещением -76) содержит адрес VMT, а другое (со смещением -48) – адрес DMT.
• Адреса виртуальных методов в VMT расположены последовательно, в порядке объявления методов в иерархии класса. Первоначально располагаются адреса методов, объявленных в текущем классе, а затем унаследованных. Адреса переопределенных методов также включаются в VMT, что обеспечивает возможность применения директивы Inherited.
• Адреса динамических методов, объявленных в данном классе, имеют отрицательные индексы (смещения) относительно таблицы VMT. Таблица DMT хранит адреса только тех методов, которые объявлены в данном классе.
• После указателя на класс располагаются поля данных класса, начиная с предков. Последними располагаются поля данных текущего класса. Генерирование информации для RTTI осуществляется с ключом $М+. RTTI играет самостоятельную важную роль и может использоваться явно и неявно. В ОР определены два оператораIs и As, неявно использующие RTTI.
Таблица 1
Смещ | Тип | Константа | Описание |
-76 | Pointer | vmtSelfPtr | Указатель на таблицу VMT (или Nil) |
-72 | Pointer | vmtIntfTable | Указатель на таблицу интерфейсов (или Nil) |
-68 | Pointer | vmtAutoTable | Указатель на таблицу информации об Automation (или Nil) |
-64 | Pointer | vmtInitTable | Указатель на таблицу инициализации (или Nil) |
-60 | Pointer | vmtTypeInfo | Указатель на таблицу информации о типе (или Nil) |
-56 | Pointer | vmtFieldTable | Указатель на таблицу определения полей (илиNil) |
-52 | Pointer | vmtMethodTable | Указатель на таблицу определения статических методов (или Nil) |
-48 | Pointer | vmtDynainicTable | Указатель на DMT (или Nil) |
-44 | Pointer | vmtClassName | Указатель на строку с именем класса |
-40 | Cardinal | vmtInstanceSize | Размер экземпляра в байтах |
-36 | Pointer | vmtParent | Указатель на родительский класс (или Nil) |
-32 | Pointer | vmtSafecalIException | Указатель на метод SafecallException (или Nil) |
-28 | Pointer | vmtAfterConstruction | Адрес метода AfterConstruction |
-24 | Pointer | vmtBeforeDestruction | Адрес метода BefbreDestruction |
-20 | Pointer | vmtDispatch | Адрес метода Dispatch |
-16 | Pointer | vmtDefaultHandler | Адрес метода DefaultHandler |
-12 | Pointer | vmtNewInstance | Адрес метода Newlnstance |
-8 | Pointer | vmtFreeInstance | Адрес метода Freelnstance |
-4 | Pointer | vmtDestroy | Адрес деструктора Destroy |
Pointer | vmtQuery Interface | Адрес метода Querylnterface | |
Pointer | vmtAddRef | Адрес метода AddRef | |
Pointer | vmtRelease | Адрес метода Release | |
Pointer | vmtCreateObject | Адрес метода CreateComObject |
Проверка типа
ОператорIs предназначен для проверки совместимости по присвоению экземпляра какого-нибудь класса с заданным классом. Выражение вида:
If AnObject Is TClassType Then TClassType(AnObject).<метод>;
приводит к выполнению <метода> класса TClassType тогда, когда выражение AnObject Is TClassType принимает значение True. А это происходит только в том случае, если объект AnObject совместим по присвоению с классом TClassType, т.е. является экземпляром этого класса или одного из порожденных от него классов-потомков.
Приведение типа
Приведение типа значения (value typecasting) - это операция изменения типа выражения на какой-либо другой. Оба типа - и тип выражения, и результирующий - должны быть или порядковыми типами, или указателями.
Оператор As введен в язык специально для приведения объектных типов. С его помощью можно рассматривать экземпляр класса одного типа как принадлежащий другому, но совместимому типу. Этот оператор проверяет типы переменных во время выполнения программы, после чего выполняет безопасное приведение типа. Так конструкция: