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, взятое из справочной системы, приведено на следующем рисунке.

With TButton.Create(Sell) Do Begin - student2.ru

Последовательность добавления особенностей в классы можно просле­дить на примере визуального класса, реализующего кнопки управления. Эта иерархия классов представлена на следующем рисунке.

With TButton.Create(Sell) Do Begin - student2.ru На каждом уровне иерархии добавляются важные возможности для класса:

TObiect - Включает более 25 методов, общих для всех объектов (17 Delphi 1).

» TPersistent - Добавляет возможность писать самого себя в ЕХЕ файл во время компиляции и переносить себя обратно из ЕХЕ файла во время вы­полнения.

TComponent - Вводит имя компонента (Name), множество состояний объекта (чтение, запись, выборка и т.п.), указатель на владельца (Owner), обеспечивает возможность создания компонентов во время выполнения про­граммы с соответствующей регистрацией компонентов в списке.

TControl - Добавляет возможность взаимодействия с пользователем.

TWinControl - Добавляет возможность использовать механизмы Windows для создания окон.

TButtonControl - Обеспечивает работу с кнопками.

TButton - Реализует "реальные" кнопки с конкретными возможностя­ми: изменение поверхности, опускание кнопки и т.п.

RTTI

Переменная типа класса представляет собой 4-х байтный указатель на экземпляр класса, который и является объектом. Внутренний формат данных объекта похож на запись. Каждый экземпляр класса содержит отдельную ко­пию его полей. Поля, как уже указывалось, располагаются в порядке объяв­ления, начиная с предков. Рассмотрим внутреннюю структуру объекта, кото­рая приведена на следующем рисунке. With TButton.Create(Sell) Do Begin - student2.ru

• Первое поле каждого экземпляра класса хранит указатель на свой класс, точнее на начало специальной 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 введен в язык специально для приведения объектных ти­пов. С его помощью можно рассматривать экземпляр класса одного типа как принадлежащий другому, но совместимому типу. Этот оператор проверяет типы переменных во время выполнения программы, после чего выполняет безопасное приведение типа. Так конструкция:

Наши рекомендации