4.2. Сложные типы языка

We use cookies. Read the Privacy and Cookie Policy

Среди сложных типов первым традиционно рассматривается массив — упорядоченная структура однотипных данных, хранящая их последовательно. Массив обязательно имеет размеры, определяющие, сколько элементов хранится в структуре. До любого элемента в массиве можно добраться по его индексу.

Тип «массив» определяется конструкцией

Array [диапазон] of ТипЭлементов;

Диапазон в квадратных скобках указывает значения индексов первого и последнего элемента в структуре. Примеры объявления типов:

| TYPE

| Array01to10 = Array[ 1..10] of Real;

| Array11to20 = Array [11..20] of Real;

Здесь мы вводим два типа. Они совершенно одинаковы по структуре, но по-разному нумеруют свои элементы. Оба типа содержат наборы из десяти значений типа Real.

Пусть определены переменные именно таких типов (скажем, a01to10 и a11to20). Доступ к i-му элементу массивов осуществляется через запись индекса в квадратных скобках сразу за именем массива: a01to10[i] или a11to20[i].

Возможно объявление таких конструкций, как массив массивов (это будет, по сути, матрица) или других структур. Подробнее массивы будут рассмотрены в разд. 7.1 «Массивы (Array) и работа с ними».

- 70 -

Другим сложным типом является множество, конструируемое специальной фразой

Set of БазовыйПеречислимыйТип.

Данные типа «множество» — это наборы значений некоего базового перечислимого типа, перечисленные через запятую в квадратных скобках. Так, если базовым считать введенный ранее перечислимый тип Test, то значение типа

Set of Test

может содержать произвольные выборки значений типа Test:

[Level0]

[Level3, Leve4]

[Level1..Level5],

и т.п., а также

[] — пустое множество.

Множество отличается от массива тем, что не надо заранее указывать количество элементов в нем, используя индексацию. Множество может расширяться или сокращаться по ходу программы. В Паскале определены операции над множествами, аналогичные математическим: объединение множеств, поиск пересечения их (взятие разности множеств), выявление подмножеств и др. Излишне говорить, что такой тип данных существенно расширяет гибкость языка. Подробно множества описываются в разд. 7.3 «Тип «множество» (Set). Операции с множествами».

Файловый тип — это «окно в мир» для программы на Турбо Паскале. Именно с помощью файловой системы осуществляется весь ввод и вывод информации программой. Этим вопросам в книге посвящена гл. 12, здесь же ограничимся общим определением файла. Файл (любого типа) — это последовательность данных, расположенных вне рабочей памяти программы (на магнитном диске, на экране, на принтере, в другом компьютере в сети ПЭВМ или где-нибудь еще). Некоторые файлы могут только выдавать информацию (например, клавиатура). Другие файлы могут только принимать ее, например, устройство печати. Напечатанный принтером лист — это зримый образ выведенного программой файла. Третьи файлы позволяют и считывать из себя информацию, и записывать ее. Примером является обычный файл на диске. Определяя файлы в программе, мы можем через них общаться с периферией ПЭВМ, и в том числе накапливать данные и впоследствии обращаться к ним.

- 71 -

Файловые типы Турбо Паскаля (Text, File of... и File) различаются только типами данных, содержащихся в конкретных файлах программы. Задавая в программе структуры данных типа «файл», мы определяем тип этих данных, но не оговариваем их количество в файле. Теоретически файл может быть бесконечной последовательностью данных; практически же на все случаи жизни в ПЭВМ найдутся ограничения, в том числе и на длину файла.

Следующий сложный тип языка — записи. Для тех, кто не знаком с языком Паскаль, это слово поначалу ассоциируется не с тем, что оно на самом деле обозначает. Да, запись может быть записью на диске. Но в исходном значении — это структура данных, аналогичная таблице. У обычной таблицы есть имя, и у каждого ее поля тоже есть имя. Похожим образом в типе данных «запись» указываются названия полей и тем самым вводятся в работу табличные структуры данных. Мы можем, например, ввести тип данных, аналогичный анкете (т.е. той же таблице):

| TYPE

| PERSON=RECORD

| F_I_O_ : String; { фамилия, имя, отчество}

| Ves.Rost : Real; { вес и рост}

| Telephone : Longint { номер телефона}

| END;

В этом определении слово RECORD открывает набор имен полей таблицы-анкеты и типов значений в этих полях, a END — закрывает его, т.е. пара RECORD...END конструирует тип «запись». Тип PERSON теперь задает таблицу из строки (F_I_O_), двух чисел с дробной частью (Ves, Rost) и одного целого числа. Все они называются полями записи типа Person. Далее мы можем ввести в программе переменную Nekto типа Person, и под именем Nekto будет пониматься анкета-таблица с конкретными значениями. Доступ к полям таблицы производится дописыванием к имени всей таблицы имени нужного поля. Имя переменной-записи (оно же имя таблицы) и имя поля разделяются точкой:

Nekto.F_I_O_ — значение строки с фамилией, именем, отчеством;

Nekto.Ves — значение поля Ves.

Полями записей может быть что угодно, даже другие записи. Количество полей может быть велико. Записи частично схожи с массивами: они тоже хранят определяемое заранее количество данных. Но в отличие от массивов и множеств компоненты записи могут иметь разные типы, и доступ к ним происходит не по индексу, а по имени. Записи позволяют существенно упростить обработку слож-

- 72 -

ных структур, а их использование делает программу более «прозрачной».

Очередной тип, который мы рассмотрим — это объекты. Объект (object) — это принципиально новый тип, вводимый Турбо Паскалем, начиная с версии 5.5 языка. Но это не только новый тип. Это новый подход к программированию. Что такое объект? Представьте себе, что мы сгруппировали некие данные в запись. Это удобно, ибо разнотипные значения теперь хранятся «под одной крышей». В программе эти данные обрабатываются какими-либо методами. Очень часто бывает, что эти методы годны только для обработки полей нашей записи и не работают с другими данными. Но раз так, то не будет ли рациональнее внести методы в список полей самой записи? Как только мы это проделаем, получим новый тип данных — объект.

В программе объекты описываются почти так же, как записи:

TYPE

DataWithMethods = OBJECT

Поле данных 1: его Тип;

Поле данных 2: его Тип;

...

Метод 1;

Метод 2;

Метод 3;

...

END;

Список полей и методов должен начинаться словом OBJECT и заканчиваться END (все об объектах читайте в гл. 13 «Объектно-ориентированное программирование»).

Таким образом, объект — это замкнутый мир данных и средств их обработки. Методы, реализуемые как процедуры и функции, имеют смысл и могут применяться только к полям данных этого же объекта. В то же время объекты привносят новые подходы к построению программ. Вводится такое понятие, как наследование признаков объектов. Это значит, что можно построить ряд все более и более сложных объектов, каждый из которых наследует свойства (данные и методы их обработки) предшественника и является его развитием. А объявив в программе такой ряд объектов, можно будет построить процедуры, которые смогут работать (запускать методы) с любым объектом этого ряда. (Возможность использовать одну процедуру для целого ряда взаимосвязанных через наследование объектов называется полиморфизмом.)

Язык Паскаль традиционно считается хорошим инструментом структурного программирования. Турбо Паскаль дает возможность

- 73 -

использовать другой подход к написанию программ — объектно-ориентированный. И если в первом случае стоит задача разделить алгоритм решения на отдельные процедуры и функции, то во втором — представить задачу как совокупность взаимодействующих объектов, выстраивая при этом ряды объектов — от низшего уровня данных к более высоким — согласно принципу наследования. И если вдруг изменится нижний уровень представления объекта, то достаточно будет изменить только его: все изменения автоматически передадутся по цепочке наследования. Если же, наоборот, понадобится еще больше усложнить объект, то достаточно будет просто продолжить ряд наследования. А процедуры (по свойству полиморфизма) останутся теми же.

Последним среди сложных типов Турбо Паскаля является ссылочный тип. В разд. 4.1.6 рассматривался тип Pointer — адресный тип. Его значения — это указатели на какую-либо ячейку рабочей памяти ПЭВМ. Причем не оговаривается, какое значение и какого типа в этой ячейке может содержаться — оно может быть каким угодно. Но известно, что структуры данных, занимающие более одной ячейки памяти, располагаются последовательно: в виде сплошной цепочки значений. Поэтому, чтобы просто адрес можно было назвать адресом какой-либо структуры данных, надо, кроме адреса первой ячейки структуры, знать еще ее тип и размер. Ссылочный тип — это тот же адресный тип, но «знающий» размер и структуру того куска памяти, на который будет организован указатель. Такие «знающие» указатели называются ссылками. Чтобы описать ссылочный тип, мы должны указать имя базового типа, т.е. тип той структуры (а именно он определяет размер и расположение данных), на которую будет указывать ссылка, и поставить перед ним знак «^», например:

| TYPE

| Dim100 = Array[1..100] of Integer; { просто массив }

| Dim100SS = ^Dim100; { ссылка на структуру типа Dim100 }

Значения типа Dim100SS (ссылки на массив) будут содержать адрес начала массива в памяти. А так как ссылка (пусть она имеет имя SS) «знает», на что она указывает, можно через нее обращаться к элементам массива. Для этого снова используется знак «^», но ставится он уже после имени переменной:

SS^ — массив типа Dim100,

SS^[2] — второй элемент массива SS^, но

SS — адрес массива в памяти.

- 74 -

Узнав все это, изучающие Паскаль обычно спрашивают, зачем столько сложностей. Есть ведь обычные массивы, и можно с ними работать, не вводя промежуточные ссылочные типы. Конечно, можно. Но использование ссылочного типа дает нам уникальную возможность располагать данные там, где мы хотим, а не там, где им предпишет компилятор. Турбо Паскаль вводит специальный набор средств для организации структур данных по ходу выполнения программы. Используя его совместно со ссылками, мы можем явно указать, где будет размещена структура данных, можем разместить ее в свободной от программы памяти ПЭВМ и впоследствии удалить оттуда. Все это позволяет очень гибко использовать отнюдь не безграничные ресурсы памяти ПЭВМ.

Такова вкратце система сложных типов Турбо Паскаля. Она достаточно развита, чтобы решать большинство практических задач. На ее основе всегда можно сконструировать структуры данных «недостающих» типов, например списки, двоичные деревья и многое другое.

- 75 -