Множества
Множество - это группа элементов, которая ассоциируется с ее именем и с которой можно сравнивать другие величины, чтобы определить, принадлежат ли они этому множеству. Один и тот же элемент не может входить в множество более одного раза. Как частный случай, множество может быть пустым.
Множества определяется перечислением его элементов, заключенным в прямоугольные скобки. Такая форма определения называется конструктором множества. Например, если множество возможных единичных символов, которые могут быть получены в ответ на вопрос программы "Yes/No", содержит символы "y", "Y", "n" и "N", то это множество можно описать таким конструктором:
['y','Y','n','N']
Для определения, принадлежит ли переменная множеству, служит операция in. В предыдущем примере проверить, дал ли пользователь один из допустимых ответов, можно оператором:
if(keyin['y','Y','n','N'])
then<оператор, выполняемый при допустимом ответе>
Множества могут содержать не только отдельные значения, но и ограниченные типы. Например, если вы хотите контролировать символы, вводимые пользователем при вводе целого положительного или отрицательного числа, вы можете определить множество ['0
'..'9', '+', '-'] и использовать его, например, при обработке события OnKeyPressкакого-то окна редактирования:
If not (Key in ['0'..'9', '+', '-']) then Key:=#0;
Подобный оператор не позволяет пользователю ввести какие-то символы, отличные от имеющихся в множестве.
В приведенных операторах множество заранее не объявлялось в виде типа. Но если, например, в приложении в ряде мест надо проводить проверки, аналогичные приведенным выше, то целесообразнее объявить переменную или типизированную константу типа множества или тип множества и несколько переменных этого типа. Объявление типа множества делается в форме setof<базовый тип>. Приведем примеры.
Объявление глобальной переменной с инициализацией (в Delphi1 это не допускается):
var
K: set of Char=['0'..'9', '+', '-'];
...
if (key in K) then ...
Объявление типизированной константы:
const
K: set of Char=['0'..'9', '+', '-'];
Объявление типа множества и переменных этого типа:
type
TDigit = set of '0'..'9';
var
D1, D2: TDigit;
...
D1:=['0','1'];
D2:=['2'..'9'];
Помимо операции inдля множеств определен еще ряд операций: объединение, пересечение, операции отношения и ряд других.
Тип variant
ObjectPascalявляется строго типизированным языком. Но в нем есть типvariant, отступающий от этого правила. В переменных типаvariantмогут храниться данные любых типов, кроме записей, множеств, статических массивов, файлов, классов, ссылок на классы, указателей иInt64. Иначе говоря, переменные типаvariantмогут хранить все, кроме структур, указателей иInt64. Они могут также хранить объектыCOMиCORBA, обеспечивая доступ к их методам и свойствам. Могут они также хранить динамические массивы и массивыvariant.
Например, если определить тип переменной V какvariant, то могут выпол-
няться такие операторы:
V: variant; // тип V не определен (равен Unessigned)
…
V := 5; // тип V становится равным integer
V := lel0; // тип V становится равным real
V := Editl.Text; // тип V становится равным string
Тип variantимеет смысл использовать в тех случаях, когда тип того или иного объекта заранее не известен или когда какие-то функции и процедуры требуют именно такой тип аргументов. При этом надо иметь в виду, что затраты памяти и времени на работу с переменными типаvariantбольше, чем при работе с обычными типами. К тому же недопустимые операции с переменными типаvariantприводят к ошибкам времени выполнения, тогда как аналогичные недопустимые операции с переменными других типов выявляются на этапе компиляции.
Переменные типа variantзанимают 16 битов и содержат код типа и значение переменной или указатель на это значение. В момент создания эти переменные инициализируются специальным значениемUnassigned. Значение переменнойnullсвидетельствует о неизвестном или ошибочном значении переменной.
Переменные типа variantмогут использоваться в выражениях как операнды любых операций, кроме ^,isиin, совместно с другими величинами типовvariant,integer,real,string,boolean. Компилятор в этих случаях автоматически осуществляет приведение типов величин в выражении. Если оба операнда операции имеют типvariantи один или оба операнда равныnull, то результат операции тоже равенnull. Если один или оба операнда имеют значениеUnassigned, то генерируется исключение. Если в бинарной операции только один из операндов имеет типvariant, то другой тоже преобразуется в типvariant.
Приведение типов при вычислении выражений, содержащих операнды variant, осуществляется обычным образом. Например, еслиV1 иV2 типаvariantсодержат данные типовintegerиreal, то выражениеV1 +V2 вернет значениеreal.
Узнать действительный тип значения переменной variantможно с помощью функцииVarType, возвращающей значение типаTVarData, содержащее код типа. ЗаписьTVarData определена в модуле System. Имеется также предопределенная константаvarTypeMask, сложение которой по операции and с переменной типаTVarData возвращает истинный тип переменной. Например, выражение
VarType(V) and varTypeMask = varDouble
вернет true, если в переменной V в данный момент хранится значение типаdouble
или массив значений типа double.
Возможные значения типов, возвращаемые функцией VarType, следующие:
|
varEmpty |
переменная в состоянии Unassigned |
|
varNull |
значение переменной равно null |
|
VarSmallint |
тип Smallint |
|
varInteger |
тип Integer |
|
varSingle |
тип Single |
|
varDouble |
тип Double |
|
varCurrency |
тип Currency |
|
varDate |
тип TDateTime (дата И время) |
|
varOLEStr |
ссылка на динамически размещенную строку UNICODE |
|
varDispatch |
ссылка на автоматический объект (указатель на интерфейс IDispatch)
|
|
varError |
код ошибки операционной системы |
|
varBoolean |
тип WordBool |
|
varUnknown |
ссылка на неизвестный объект СОМ (указатель на интерфейс (IUnknown) |
|
varByte |
тип Byte |
|
varString |
ссылка на динамически размещенную строку в стиле Pascal (тип AnsiString). |
|
varTypeMask |
битовая маска для извлечения кода типа |
|
varArray |
бит, устанавливаемый при ссылке на массив variant |
|
varByRef |
бит, устанавливаемый при ссылке на тип variant |
Теперь остановимся на массивах типа variant. Переменной типаvariant нельзя присвоить значение обычного статического массива. Это можно сделать только специальными функциямиVarArrayCreate и VarArrayOf. ФункцияVarArrayCreate определена следующим образом:
function VarArrayCreate(const Bounds: array of Integer; VarType: Integer): Variant;
Здесь параметр Bounds является массивом, содержащим четное количество целых чисел, каждая пара которых определяет нижнее и верхнее значения индекса массива (точнее, размерности массива, если массив многомерный). ПараметрVarType определяет тип элементов массива. Он может принимать значения, приведенные выше в таблице, кромеvarString, varArray, varByRef. Например, операторы
var
V:Variant;
…
V:=VarArrayCreate([0,9],varInteger);
создают в переменной V типа variant массив из десяти целых чисел. Операторы
var
A: Variant;
…
А := VarArrayCreate([0, 3], varVariant);
А[0] := 1;
А[1] :- 1234.5678;
А[2] := 'Привет!';
А[3] := True;
Labell.Caption := А [ 0 ] ;
Label2.Caption := A [ 2 ] ;
создают в переменной А типа массив из четырех значений типа variant, в которые можно заносить и затем использовать значения различных типов.
Функция VarArrayOf определена следующим образом:
function VarArrayOf(const Values: array of Variant): Variant;
Она возвращает одномерный массив элементов, задаваемых параметром Values.
Например, приведенный выше пример можно дополнить операторами
А[3]:= VarArrayOf ([1, 'Приветик! ', 100, 1000]);
Label3.Caption : = А [ 3 ] [1 ] ;
