Современный язык Delphi приобрел возможность работы с шаблонами или, говоря точнее, с обобщенными типами (generics types) данных. Своим появлением на свет шаблоны обязаны желанием разработчиков развить возможности ООП. Именно в языках программирования, основанных на ООП, код приобрел истинную универсальность и стал позволять программистам повторно использовать первоначально разработанный алгоритм для решения новых задач. Создав исходный класс для применения в какой-то прикладной задаче, мы имеем возможность перенести свой класс (или его потомков) в другой проект. Однако обычные классы, пусть даже усиленные за счет наследования, инкапсуляции и полиморфизма, далеко не универсальны, ведь их методы и свойства нацелены на обслуживание строго определенных типов данных. Концепция обобщенного типа данных как раз и предназначена для устранения этого недостатка — она позволяет программисту абстрагироваться от типа данных. Благодаря шаблонам разработчик получает возможность создавать алгоритмы, не указывая типы данных, с которыми он работает. Услуги обобщенного типа данных окажутся весьма кстати при описании схожих алгоритмов, занимающихся обработкой разноплановых данных. Например, это позволяет реализовать классические алгоритмы сортировки массивов самых разнообразных типов данных в рамках одного и того же метода класса.
конкретных типов данных, с которыми он работает.
Обобщенный тип данных в полях записей
Основные приемы работы с обобщенным типом данных наиболее просто продемонстрировать с помощью записи Delphi. Еще в первых версиях языка Pascal появилась запись — структурный тип, специализирующийся на предоставлении доступа к некоторому перечню разнотипных полей. В современных версиях Delphi программисту представилась уникальная возможность включать в состав записи не только строго типизированные поля, но и поля-обобщения, т. е. поля, тип данных которых заранее не определен. Описание шаблона записи с полями обобщенного типа выглядит следующим образом:
type имя_ типа_записи <имя_обобщенного_типа [, . . .]> = record имя_поля: имя_ обобщенного__ типа;
[Другие поля] end;
Наличие угловых скобок уведомляет нас, что запись намерена работать с обобщенным типом данных. Внутри угловых скобок перечисляются параметры типов (type parameters). С одной стороны, параметр типа — это имя переменной, которое мы задействуем внутри исходного кода класса в тех местах, где используется соответствующий тип данных. С другой стороны, параметр типа — это псевдоним типа данных, которым воспользуется программист при обращении к классу извне.
Отметим, что при определении имени обобщенного типа нет необходимости вспоминать о существовании предопределенных типов данных Delphi. Имя обобщенного типа — это всего лишь псевдоним какого-то заранее неизвестного типа данных, во время выполнения программы им может оказаться целое или вещественное число, строковый или символьный тип либо какой-то другой тип данных.
Листинг 3.1 демонстрирует порядок объявления шаблона записи с полями обобщенного типа. Перечень имен, используемых в записи обобщенных типов данных, приводится внутри угловых скобок, сразу за названием типа записи.
type TGenericRec<T,R>= record
A : char; //в любом случае это символьное поле
В,С : Т; //поля обобщенного типа Т
D : R; //поле обобщенного типа R
end;
var GRecl:TGenericRec<integer,double>; //объявление переменной GRecl GRec2:TGenericRec<boolean, string>; //объявление переменной GRec2begin
GRecl.B:=15; //полеВ хранит целое значение
GRecl.D:=0.675;//поле D хранит вещественное значение //...
GRec2.B:=true; //поле В хранит булев тип данных GRec2.D:=fHello,World!1; //в поле D находится строка с текстом //...
end.
Во время инициализации переменных имена обобщенных типов заменяются названиями реальных типов данных. В нашем примере при объявлении GReci (см. листинг 3.1) вместо обобщения т мы задействуем целочисленный тип integer, вместо r— вещественный тип double. При объявлении GRec2 мы меняем правила игры: теперь обобщенный тип т замещается типом boolean, r — string.