Скачиваний:
15
Добавлен:
01.05.2014
Размер:
112.89 Кб
Скачать

2.3.1.2. Наследование атрибутов

Атрибутами типа являются:

  • множество значений;

  • литеральные обозначения констант;

  • множества определенных для типа операций.

При использовании структурной эквивалентности производный тип может унаследовать все атрибуты порождающего типа.

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

Пример

Программа вычисления площади прямоугольника

program square_figure (input, output);

type length = real;

square = real;

var x, y: length;

s: square;

begin

read (x, y);

s := x * y;

writeln(s)

end.

Если операция "*" наследуется от типа вещественный, то разумно предположить, что и тип результата операции x*y такой же, как и тип операндов, т.е. length (длина). Следовательно, оператор присваивания

s := x * y

недопустим!

Можно использовать функцию преобразования типа

s := square(x * y) ,

ЯП 2-12

но это не очень хорошо, так как назначение производных типов состоит в запрещении некорректных операций, а не в ограничении кор­ректных.

С другой стороны, оператор x := x * y корректен, но является бессмыслицей с точки зрения размерности.

Вывод

При полной реализации высокой надежности за счет использова­ния производных типов язык должен обладать механизмом переопреде­ления существующих операций и механизмом определения новых опера­ций.

В современных языках программирования операции, как правило, перегружены и, как следствие этого, например, операция "+" для сложения целых чисел отличается от операции сложения вещественных чисел. Какая операция имеется в виду в каждом конкретном случае определяется компилятором путем исследования типов операндов и предполагаемого результата.

Обычно операция присваивания := и операции отношения =, <, > корректны для любого типа. Для других же операций необходимо пре­дусмотреть возможность, с помощью которой множество операций, наследуемое от порождающего типа, должно ограничиваться, а затем расширяться за счет определенных пользователем операций.

2.3.1.3. Ограничения

Для повышения надежности языка можно ограничить также насле­дуемое множество значений. Максимальная надежность достигается при ограничении для объекта его области значений в точности до требуемой.

Ограничение диапазона можно включить непосредственно в опи­сание производного типа, например,

type index = 1..100; // Паскаль

type index = integer range 1..100; // Ада

При использовании ограничения диапазона наряду с повышением надежности имеет место повышение эффективности выполнения прог­раммы.

ЯП 2-13

Пример

Если индекс i описан с использованием типа index, то при компиляции следующего фрагмента программы

Summa := 0;

for I := 1 to 100 do summa := summa+a[i];

компилятор может не вставлять код для проверки истинности условий

i >= 1 и i <= 100

при вычислении элемента массива a[i].

2.3.2. Подтипы

В некоторых случаях оказывается логически нецелесообразным вводить новый тип только для введения ограничений. Ограничить ди­апазон значений объектов из заданного класса без изменения их статуса как членов этого класса можно с помощью понятия подтипа.

Например, описание

sybtype shortint = integer range -128 .. 127

определяет подтип shortint. При этом объекты подтипа shortint мо­гут использоваться совместно с объектами типа integer без исполь­зования явного преобразования типа.

С точки зрения программиста единственное различие между про­изводным типом и подтипом заключается в том, что первый вводит совершенно новый класс объектов, отличный от всех остальных, в то время как второй просто накладывает ограничения на существующий.

Реализация же производных типов и подтипов может оказаться совершенно различной. Причина этого заключается в том, что всегда безопасно представлять производный тип на базовом машинном обору­довании наиболее эффективным способом. Подтипы же требуют такой реализации, которая бы учитывала вид реализации порождаемого типа.