Язык Ада, 03 лекция (от 10 марта)
Материал из eSyr's wiki.
Содержание |
Лекция №3.
Покомпонентное сложение двух неограниченных массивов
Рассмотрим удобство атрибутов при работе с массивами. Допустим для неограниченного массива нужно определить покомпонентное сложение. Если слагаемые разной длины, то это стоит трактовать как нарушение подтиповых ограничений. Однако одинаковая длина массивов не гарантирует совпадение индексных диапазонов. Для того, чтобы привести дискретное значение типа индекса к порядковому номеру, используется атрибут Pos, вычисляется необходимый сдвиг для порядкового номера и возвращение к соответствующему значению индексному значению происходит с помощью атрибута Val. Параметры функции «+» Left и Right объявлены как имеющие тип Arr, индексный диапазон которого не уточнен. Но Left и Right — это формальные параметры, на место которых при вызове функции «+» будут подставлены конкретные массивы с известными индексными диапазонами. В теле функции «+» можно пользоваться атрибутами массивов Range, First, Length, с помощью которых можно получить информацию о индексном диапазоне.
Записи с дискриминантами
Пусть есть система, которая обслуживает гараж и указывает, есть там автомобиль или нет. Автомобили бывают нескольких типов(легковой, автобус, грузовик). У автомобиля существует много атрибутов. Некоторые из них общие для всех(серийный номер), и есть специфические для конкретного типа автомобиля. У типа есть параметры: вид и тд. Специальное поле записи, вынесенное на место параметра этого типа, называется дискриминант. Дискриминант бывает не только у записи. Пусть это перечисление общих свойств: год выпуска, … А потом с помощью конструкции case описывается разница. Case используется не как оператор, а как перебор вариантов структуры типа. Например, если он легковой, то null(нет дополнительных полей). Если он автобус, то появляется такое свойство, как число мест. Если это грузовик, то возникает поле грузоподъемность. В Аде в конструкциях типа case необходимо перечислить все возможные значения управляющей переменной, причем это контролируется компилятором. Если для какого-то значения управляющей переменной нет дополнительных полей, то нужно явным образом это написать(null). Нельзя определить объект типа Автомобиль, не сказав, какой это автомобиль. Это называется ограничения дискриминанта. Если накладывается ограничение типа на дискриминант, то это ограничение типа данных будет с этим объектом данных будет все время. У типа Автомобиль существуют варианты структуры. Когда происходит компиляция кода, нужно создать код, который будет размещать объект типа данных в памяти. Компилятор программирует параметризированный алгоритм выделения памяти, и память будет выделяться не компилятором, а во время выполнения программы. При выполнении присваивания динамически происходит следующее: какое значение дискриминанта у получателя, какое значение дискриминанта у источника. Если они не совпадают, то возникает ошибка и будет получено исключение. При присваивании полю, зависимому от значения дискриминанта происходит следующее: проверяется значение дискриминанта и существует ли для данного значения такое поле. Если не существует, то будет получено исключение. Динамически переопределить значение дискриминанта у какого-то объекта типа данных нельзя, значение дискриминанта зафиксировано и все время будет неизменно. Для дискриминанта можно задавать значение по умолчанию. При использовании значения по умолчанию для дискриминанта определяется объект не ограниченного дискриминанта, то значение дискриминанта этого объекта можно менять по ходу жизни. Но при этом действуют ограничения: например, менять значение дискриминанта можно только одновременно с изменение значения всего объекта данных. Во время выполнения программы будет проверено, что свойства тех полей, которые от дискриминанта зависят, удовлетворяют новому значению дискриминанта.
Ссылочный тип
Что делать, когда ссылка на объект есть, а самого объекта нет? При использовании acces all - ссылочный тип ссылается на значение типа Т, эти значения могут быть созданы как генератором new, так могут быть статически размещенными объектами. Допустим мы заводим global – глобальную ссылку для доступа к объекту типа данных в другом модуле. При описании типа нужно указывать ключевое слово emenist, которое указывает, что на этот объект типа Т можно создавать ссылки и присваивать значения ссылочного типа. Есть локальные указатели. Допустим, в процедуре создается какой-то объект и возвращается локальная ссылка на него. При попытке присвоить глобальной ссылке локальную ссылку, компилятор «наругается», тк это потенциально опасное место, где может возникнуть «дохлая» ссылка. После того, как процедура отработала, у глобальной ссылке есть какое-то значение, но куда оно ссылается – неизвестно. В Аде действует такое правило: ссылка не может быть более глобальной, чем то, на что она ссылается. И это компилятор старается проверять статически. Но можно создать такую ссылку, в которой отключается контроль за такими ситуациями, но это нужно явно указывать.
Пакеты
В пакетах отдельно спецификация, отдельно тело. Пакет может содержать в себе объявления чего угодно, кроме тела программных модулей. В теле пакета повторяются тела всех программных модулей, которые объявлены в спецификации. Тело пакета клиентам пакета не доступно, не видно никак. С помощью ключевого слова private можно указывать все то, что необходимо скрыть от клиента. Клиент может пользоваться только тем, что написано в видимой части пакета. Допустим, очередь, которая реализована через массив, и где пользователю доступны несколько операций работы с очередью, является абстрактным типом данных. Смысл абстрактного типа данных(не в смысле ООП) в том, что в этот тип данных не «пролезают» детали его реализации, которые клиенту не нужны.
Шаблоны
В шаблонах соблюдаются концепция строгой типизации. В Аде используются контрактные модели. При определении шаблона можно в качестве параметра этого шаблона описывать формальные типы, задавая свойства этих формальных типов. При реализации шаблона можно пользоваться теми свойствами формального типа, которые для них заданы. Когда достраивается шаблон, то необходимо, чтобы фактические типы имели как минимум те свойства, которые присутствуют в формальных типах. Для реализации шаблона для покомпонентного сложения массивов необходимо, чтобы для типа массива была определена операция присваивания и операция сложения. Индексные типы имеют дискретный тип, а любой дискретный тип с помощью атрибута Pos можно перевести в порядковый номер, для которого определены операции сложения.