Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 700269.doc
Скачиваний:
15
Добавлен:
01.05.2022
Размер:
1.78 Mб
Скачать

3.3.9. Вариантные типы

В переменных типа variant могут храниться данные любых типов, кроме структур и указателей. Тип variant имеет смысл использовать в тех случаях, когда тип того или иного объекта заранее не известен или когда какие-то функции и процедуры требуют именно такой тип аргументов. При этом надо иметь в виду, что затраты памяти и времени на работу с переменными типа variant больше, чем при работе с обычными типами. К тому же недопустимые операции с переменными этого типа приводят к ошибкам времени выполнения, тогда как аналогичные недопустимые операции с переменными других типов выявляются на этапе компиляции.

Переменные типа variant занимают 16 битов и содержат код типа и значение переменной или указатель на это значение. Узнать действительный тип значения переменной variant можно с помощью функции VarType, возвращающей значение типа TVarData, содержащее код типа. Переменные типа variant могут использоваться в выражениях как операнды любых операций, кроме ^, is и in, совместно с другими величинами типов variant, integer, real, string, boolean. Компилятор в этих случаях автоматически осуществляет приведение типов величин в выражении.

3.3.10. Объекты, классы и интерфейсы

Класс – это тип данных, определяемый пользователем. То, что в Delphi имеется множество предопределенных классов, не противоречит этому определению – ведь разработчики Delphi тоже пользователи Object Pascal. Понятие объекта (object) использовалось при зарождении объектно-ориентирован­ного программирования при переходе от Pascal к Object Pascal. В настоящее время тип object практически эквивалентен классу. В научно-технической литературе можно встретить иную интерпретацию термина "объект" – как конкретный экземпляр или инициализированную переменную класса.

Класс должен быть объявлен до того, как будет объявлена хотя бы одна переменная этого класса. Синтаксис объявления следующий.

Type

<имя класса> = Class (<имя класса - родителя>)

public {доступно всем}

<поля, методы, свойства, события>

published {видны в Инспекторе Объекта и изменяемы}

<поля, свойства>

protected {доступ только потомкам}

<поля, методы, свойства, события>

private {доступ только в модуле}

<поля, методы, свойства, события>

end;

Имя класса может быть любым допустимым идентификатором, однако идентификаторы большинства классов принято начинать с символа "T". Имя класса-родителя может не указываться. Тогда предполагается, что данный класс является непосредственным наследником TObject – наиболее общего из предопределенных классов. Таким образом, эквивалентны следующие объявления:

type TMyClass = class

...

end;

type TMyClass = class(TObject)

...

end;

Класс наследует поля, методы, свойства, события от своих предков и может отменять какие-то из этих элементов класса или вводить новые. Доступ к объявляемым элементам класса определяется тем, в каком разделе они объявлены.

Раздел public (открытый) предназначен для объявлений, которые доступны для внешнего использования. Это открытый интерфейс класса. Раздел published (публикуемый) содержит открытые свойства, которые появляются в процессе проектирования на странице свойств Инспектора Объектов и которые, следовательно, пользователь может устанавливать в процессе проектирования. Раздел private (закрытый) содержит объявления полей, процедур и функций, используемых только внутри данного класса. Раздел protected (защищенный) содержит объявления, доступные только для потомков объявляемого класса. Как и в случае закрытых элементов, можно скрыть детали реализации защищенных элементов от конечного пользователя. Однако, в отличие от закрытых, защищенные элементы остаются доступны для программистов, которые захотят производить от этого класса производные объекты, причем не требуется, чтобы производные объекты объявлялись в этом же модуле.

Объявления полей выглядят так же, как объявления переменных или объявления полей в записях. Объявления методов в простейшем случае также не отличаются от обычных объявлений процедур и функций.

Интерфейсы во многом напоминают интерфейсную часть классов. Но они содержат только объявления методов и не содержат их реализацию, которая должна осуществляться в классах, поддерживающих данный интерфейс. Однако в приложении могут создаваться переменные типа интерфейса. Через них можно обращаться к объявленным в интерфейсе методам объектов классов, использующих данный интерфейс, точно так же, как это делается при непосредственном обращении к объектам. Особенность заключается в том, что при обращении через интерфейс можно работать с объектами разных классов (в том числе с объектами классов, не имеющими общего предка), в которых определены используемые методы. Таким образом, возможна реализация полиморфного поведения объектов совершенно различных классов. Необходимо отметить, что интерфейсы обеспечивают возможность множественного наследования, отсутствующую в классах Object Pascal.

Объявление интерфейса имеет вид:

type

<имя интерфейса>=interface(<имя интерфейса-родителя>)

['GUID']

<список элементов>

end;

Имена интерфейсов принято начинать с символа "I". Имя интерфейса-родителя может отсутствовать. В этом случае интерфейс наследует непосредственно классу IUnknown – базовому классу всех интерфейсов. Интерфейс, подобно классу, наследует от своих родителей все методы, но не наследует их реализацию. Может также отсутствовать указание GUID – глобального уникального идентификатора, который задается строкой шестнадцатеричных символов (от 0 до F) вида ['{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}'].

Объявление интерфейса в основном аналогично объявлению класса и имеет следующие ограничения:

  • список элементов может включать только методы и свойства (с соответствующими методами для чтения и записи), но не может включать поля;

  • все методы интерфейса открытые (public), т.е. при объявлении метода необходима инструкция stdcall;

  • поскольку реализация методов интерфейса определяется в классе, поддерживающем данный интерфейс, то интерфейсные методы не могут быть виртуальными, динамическими, абстрактными, не могут перегружаться, также интерфейс не имеет конструктора и деструктора.