logo
Языки программирования

4.5. Подтипы

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

Temperature: Integer;

Temperature := -280; -- Ниже абсолютного нуля!

Compass-Heading: Integer;

Compass-Heading := 365; - Диапазон компаса 0..359 градусов!

Предположим, что мы попытаемся определить новый класс типов:

type Temperatures is Integer range -273 .. 10000; - - He Ada!

type Headings is Integer range 0 .. 359; -- He Ada!

Это решает проблему проверки ошибок, вызванных значениями, выходящи­ми за диапазон типа, но остается вопрос: являются эти два типа разными или нет? Если это один и тот же тип, то

Temperature * Compass_Heading

является допустимым арифметическим выражением на типе целое; если нет, то должно использоваться преобразование типов.

На практике полезны обе эти интерпретации. В вычислениях, касающихся физического мира, удобно использовать значения разных диапазонов. С другой стороны, индексы в таблицах или порядковые номера не требуют вычислений с разными типами: имеет смысл запросить следующий индекс в таблице, а не складывать индекс таблицы с порядковым номером. Для этих двух подходов к определению типов в языке Ada есть два разных средства.

Подтип (subtype) — это ограничение на существующий тип. Дискретные типы (целочисленные и перечисляемые) могут иметь ограничение диапазона.

subtype Temperatures is Integer range -273 .. 10000;

Temperature: Temperatures;

subtype Headings is Integer range 0 .. 359;

Compass_Heading: Headings;

Тип значения подтипа S тот же, что и тип исходного базового типа Т; здесь ба­зовый как у Temperatures, так и у Headings — тип Integer. Тип определяется во время компиляции. Значение подтипа имеет то же самое представление, что и значение базового типа, и допустимо везде, где требуется значение базового типа:

Temperature * Compass_Heading

это допустимое выражение, но операторы:

Temperature := -280;

Compass-Heading := 365;

приводят к ошибке, потому что значения выходят за диапазоны подтипов. На­рушения диапазона подтипа выявляются во время выполнения.

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

subtype Upper-Case is Character range 'A'.. 'Z';

U: Upper-Case;

C: Character;

U := 'a'; -- Ошибка, выход за диапазон

С := U; -- Всегда правильно

U := С; -- Может привести к ошибке

Подтипы важны для определения массивов, как это будет рассмотрено в раз­деле 5.4. Кроме того, именованный подтип можно использовать для упроще­ния многих операторов:

if С in Upper-Case then ... - Проверка диапазона

for C1 in Upper-Case loop ... — Границы цикла

Yandex.RTB R-A-252273-3
Yandex.RTB R-A-252273-4