Ada (798525), страница 6
Текст из файла (страница 6)
Это имеет значение только в выражениях вида "A* B / C" которые, при вычислении промежуточных значений, используют базовый тип. Тоесть, результат "A * B" может выходить за пределы значений типа не приводя к генерацииисключительной ситуации если общий результат вычисленного значения всего выражения будетнаходиться в допустимом диапазоне значений для данного типа.Таким образом, необходимо заметить, что проверка допустимости диапазона производитсятолько для значений подтипов, а для значений базовых анонимных типов такая проверка непроизводится. При этом, чтобы результат вычислений был математически корректен, всегдапроизводится проверка на переполнение.2.7 Производные типыМы уже рассмотрели, что подтипы остаются совместимыми со своими базовыми типами.Однако, нам может понадобиться создать абсолютно новый тип, который не будетассоциироваться ни с каким другим типом вообще, в том числе и с оригинальным типом.
Такаяконцепция типа сильно отличается от того, что принято в других языках программирования, и,даже, в прародителе Ады - Паскале.Для выполнения поставленной задачи, мы производим новый тип от другого типа, используяподобный синтаксис:type Child_Type is new Parent_Type;Такое описание создает новый тип данных - Child_Type, при этом Parent_Type - это типпредок для типа Child_Type, а тип Child_Type - это производный тип от типаParent_Type.В данном случае, тип Child_Type будет обладать такими же характеристиками что и его типпредок Parent_Type: у него такой же диапазон допустимых значений как и у типа-предка, длянего допустимы те же операции, которые допустимы для типа-предка (говорят, что типChild_Type унаследовал операции от типа-предка Parent_Type).Однако, в этом случае, производный тип Child_Type - это абсолютно самостоятельный инезависимый тип данных.
Он не совместим ни с каким другим типом, включая типParent_Type, от которого он был произведен, и другими типами, производными от типаParent_Type. Это подразумевает, что при необходимости комбинирования значений типаChild_Type со значениями типа Parent_Type требуется выполнять преобразование типов.В Аде, разрешается выполнять преобразование значений производного типа в значения типапредка и наоборот.Для того, чтобы преобразовать значение одного типа в значение другого типа необходимоуказать имя типа к которому требуется выполнить преобразование:ParentChild: Parent_Type;: Child_Type := Child_Type (Parent);-- конвертирует значение Parent,-- имеющее тип Parent_Type-- в значение типа Child_TypeОписание производного типа может указывать ограничение диапазона значений типа-предка,например:type Child_Type is new Parent_Type range Lowerbound..Upperbound;В этом случае диапазон значений производного типа Child_Type будет ограничен значенияминижней границы диапазона (Lowerbound) и верхней границы диапазона (Upperbound).Механизм производства новых типов данных из уже существующих типов позволяет создаватьцелые семейства родственных типов, которые обычно называют классами.
Так, например, типInteger принадлежит к целому классу целочисленных типов. Класс целочисленных типовявляется, в свою очередь, подмножеством более обширного класса дискретных типов.Основной смысл использования производных типов заключается в том, что для определенноготипа данных уже существует определенный набор примитивных операций и этот наборопераций можно унаследовать от такого типа при производстве от него нового типа данных.Можно создать новый тип данных и затем описать для него идентичный набор операций.Однако, при производстве нового типа данных от уже существующего типа, производный типавтоматически наследует версии примитивных операций, описанные для типа-предка.
Такимобразом, нет необходимости переписывать код заново.Например, класс дискретных типов предусматривает атрибут 'First, который наследуетсявсеми дискретными типами. Класс целочисленных типов добавляет к унаследованным от классадискретных типов операциям знак операции арифметического сложения "+". Эти механизмыболее полно рассматриваются при обсуждении тэговых типов.Производные типы используются в случаях когда моделирование определенного объектапредполагает, что тип-предок не соответствует нашим потребностям, или тогда, когда мыжелаем разделить объекты в различные, несмешиваемые классы.type Employee_No is new Integer;type Account_No is new Integer range 0..999_999;Здесь Employee_No и Account_No различные и не смешиваемые типы, которые нельзякомбинировать между собой без явного использования преобразования типов.
Производныетипы наследуют все операции объявленные для базового типа. Например, если была объявленазапись которая имела процедуры Push и Pop, то производный тип автоматически унаследуетэти процедуры.Другое важное использование производных типов - это создание переносимого кода. Адаразрешает нам создавать новые уровни абстракции, на один уровень выше чем, скажем,абстракция целого числа на последовательности битов.Это определяется использованием производных типов, без типа-предка.type Name is range <некоторый_диапазон_значений>;Например,type Data is range 0..2_000_000;В этом случае ответственность, за выбор подходящего размера для целого, ложится накомпилятор. Таким образом, для PC, этот размер может быть 32 бита, что эквивалентно типуLong_Integer, а для рабочей станции Unix, этот размер можт остаться равным 32-битномуцелому, но это будет эквивалентно типу Integer.
Такое предоставление компиляторувозможности выбирать освобождает программиста от обязанности выбирать. Поэтомуперекомпиляция программы на другой машине не требует изменения исходного текста.2.8 АтрибутыАда предусматривает специальный класс предопределенных операций, которые позволяют вудобной форме определять и использовать различные характеристики типов и экземпляровобъектов. Они называются атрибутами.Указание имени требуемого атрибута производится в конце имени экземпляра объекта(переменной, константы) или имени типа с использованием символа одинарных кавычек.имя_типа'имя_атрибутаимя_экземпляра_объекта'имя_атрибутаНекоторыми из атрибутов для дискретных типов являются:type Processors is (M68000, i8086, i80386, M68030, Pentium, PowerPC);Integer'FirstInteger'LastProcessors'Succ(M68000)Upper_Chars'Pred('C')Integer'Image(67)------наименьшее целое Integerнаибольшее целое Integerпоследующее за M68000 в типепредшествующее перед 'C' в типе ('B')строка " 67"-- пробел для '-'Integer'Value("67")-- целое значение 67Processors'Pos(M68030)-- позиция M68030 в типе-- (3, первая позиция - 0)Простым примером использования атрибутов, - для улучшения переносимости программы, может служить следующий пример описания подтипа Positive, предоставляющегоположительные целые числа:subtype Positive is Integer range 1..Integer'Last;Здесь мы получаем размер максимального положительного целого не зависимо от любыхсистемно зависимых свойств.В Ada83 для не дискретных типов, - таких как Float, Fixed, всех их подтипов и производныхот них типов, - концепции 'Pred и 'Succ - не имеют смысла.
В Ada95 - они присутствуют. Вседругие атрибуты скалярных типов также справедливы и для вещественных типов.3. Управляющие структурыУправляющие структуры любого языка программирования предназначены для описанияалгоритмов программ, или, другими словами, для описания последовательности тех действийкоторые выполняет программа во время своей работы.Управляющие структуры языка Ада по своему стилю и назначению подобны тем конструкциям,которые встречаются в большинстве других современных языках программирования.
Однако,при этом присутствуют и некоторые отличия.Как и язык в целом, управляющие структуры языка Ада, были разработаны так, чтобыобеспечить максимальную читабельность. Все управляющие структуры языка Ада можноразделить на простые и составные инструкции. Все инструкции языка Ада должны завершатьсясимволом точки с запятой. Все составные инструкции завершаются конструкцией вида "endчто-нибудь ;".3.1 Пустая инструкцияВ отличие от многих других языков программирования, в Аде явно присутствует инструкция,которая не вызывает каких-либо действий.
Такая инструкция называется пустой, и она имеетследующий вид:null;Пустая инструкция используется в тех случаях когда не требуется выполнение каких-либодействий, но согласно синтаксиса языка должна быть записана хотя бы одна инструкция.3.2 Инструкция присваиванияИнструкция присваивания используется в Аде для установки и изменения значенийпеременных. Она использует операцию присваивания, и в общем случае имеет следующий вид:result := expression;Операция присваивания ":=" разделяет инструкцию присваивания на левую и правую части(между символами двоеточия и знак равенства, пробелы - не допустимы!). В левой частизаписывается имя переменной (result) содержимому которой будет производится присваиваниенового значения.