- •1.1. Надежность
- •Конец примера
- •1.2. Удобочитаемость
- •1.3.Гибкость
- •1.4. Простота
- •1.5. Мобильность
- •1.6. Эффективность
- •2. Механизмы типизации
- •2.3. Типы данных, определенные пользователем
- •2.3.1. Производные типы
- •2.3.1.1. Эквивалентность типов
- •2.3.1.2. Наследование атрибутов
- •2.3.1.3. Ограничения
- •2.3.2. Подтипы
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 без использования явного преобразования типа.
С точки зрения программиста единственное различие между производным типом и подтипом заключается в том, что первый вводит совершенно новый класс объектов, отличный от всех остальных, в то время как второй просто накладывает ограничения на существующий.
Реализация же производных типов и подтипов может оказаться совершенно различной. Причина этого заключается в том, что всегда безопасно представлять производный тип на базовом машинном оборудовании наиболее эффективным способом. Подтипы же требуют такой реализации, которая бы учитывала вид реализации порождаемого типа.