4.6. Производные типы
Вторая интерпретация отношения между двумя аналогичными типами состоит в том, что они представляют разные типы, которые не могут использоваться вместе. В языке Ada такие типы называются производными (derived) типами и обозначаются в определении словом new:
type Derived_Dharacter is new Character;
C: Character;
D: Derived_Character;
С := D: -- Ошибка, типы разные
Когда один тип получен из другого типа, называемого родительским (parent) типом, он наследует копию набора значений и копию набора операций, но типы остаются разными. Однако всегда допустимо явное преобразование между типами, полученными друга из друга:
D := Derived_Character(C); -- Преобразование типов
С := Character(D); -- Преобразование типов
Можно даже задать другое представление для производного типа; преобразование типов будет тогда преобразованием между двумя представлениями (см. раздел 5.8).
Производный тип может включать ограничение на диапазон значений родительского типа:
type Upper_Case is new Character range 'A'.. 'Z';
U: Upper_Case;
C: Character;
С := Character(U); -- Всегда правильно
U := Upper_Case(C); -- Может привести к ошибке
Производные типы в языке Ada 83 реализуют слабую версию наследования (weak version of inheritance), которая является центральным понятием объектно-ориентированных языков (см. гл. 14). Пересмотренный язык Ada 95 реализует истинное наследование (true inheritance), расширяя понятие производных типов; мы еще вернемся к их изучению.
Целочисленные типы
Предположим, что мы определили следующий тип:
type Altitudes is new Integer range 0 .. 60000;
Это определение работает правильно, когда мы программируем моделирование полета на 32-разрядной рабочей станции. Что случается, когда мы передадим программу на 16-разрядный контроллер, входящий в состав бортовой электроники нашего самолета? Шестнадцать битов могут представлять целые числа со знаком только до значения 32767. Таким образом, использование производного типа было бы ошибкой (так же, как подтипа или непосредственно Integer) и нарушило бы программную переносимость, которая является основной целью языка Ada.
Чтобы решать эту проблему, можно задать производный целый тип без явного указания базового родительского типа:
type Altitudes is range 0 .. 60000;
Компилятор должен выбрать представление, которое соответствует требуемому диапазону — integer на 32-разрядном компьютере и Long_integer на 16-разрядном компьютере. Это уникальное свойство позволяет легко писать на языке Ada переносимые программы для компьютеров с различными длинами слова.
Недостаток целочисленных типов состоит в том, что каждое определение создает новый тип, и нельзя писать вычисления, которые используют разные типы без преобразования типа:
I: Integer;
A: Altitude;
А := I; -- Ошибка, разные типы
А := Altitude(l); -- Правильно, преобразование типов
Таким образом, существует неизбежный конфликт:
• Подтипы потенциально ненадежны из-за возможности писать смешанные выражения и из-за проблем с переносимостью.
• Производные типы безопасны и переносимы, но могут сделать программу трудной для чтения из-за многочисленных преобразований типов.
- Глава 1
- 1.2. Процедурные языки
- 1.3. Языки, ориентированные на данные
- 1.4. Объектно-ориентированные языки
- 1.5. Непроцедурные языки
- 1.6. Стандартизация
- 1.7. Архитектура компьютера
- 1.8. Вычислимость
- 1.9. Упражнения
- Глава 2
- 2.2. Семантика
- 2.3. Данные
- 2.4. Оператор присваивания
- 2.5. Контроль соответствия типов
- 2.7. Подпрограммы
- 2.8. Модули
- 2.9. Упражнения
- Глава 3
- 3.1. Редактор
- 3.2. Компилятор
- 3.3. Библиотекарь
- 3.4. Компоновщик
- 3.5. Загрузчик
- 3.6. Отладчик
- 3.7. Профилировщик
- 3.8. Средства тестирования
- 3.9. Средства конфигурирования
- 3.10. Интерпретаторы
- 3.11. Упражнения
- Глава 4
- 4.1. Целочисленные типы
- I: Integer; -- Целое со знаком в языке Ada
- 4.2. Типы перечисления
- 4.3. Символьный тип
- 4.4. Булев тип
- 4.5. Подтипы
- 4.6. Производные типы
- 4.7. Выражения
- 4.8. Операторы присваивания
- 4.9. Упражнения
- Глава 5
- 5.1. Записи
- 5.2. Массивы
- 5.3. Массивы и контроль соответствия типов
- Подтипы массивов в языке Ada
- 5.5. Строковый тип
- 5.6. Многомерные массивы
- 5.7. Реализация массивов
- 5.8. Спецификация представления
- 5.9. Упражнения
- Глава 6
- 6.1. Операторы switch и case
- 6.2. Условные операторы
- 6.3. Операторы цикла
- 6.4. Цикл for
- 6.5. «Часовые»
- 6.6. Инварианты
- 6.7. Операторы goto
- 6.8. Упражнения
- Глава 7
- 7.1. Подпрограммы: процедуры и функции
- 7.2. Параметры
- 7.3. Передача параметров подпрограмме
- 7.4. Блочная структура
- 7.5. Рекурсия
- 7.6. Стековая архитектура
- 7.7. Еще о стековой архитектуре
- 7.8. Реализация на процессоре Intel 8086
- 7.9. Упражнения
- Глава 8
- 8.1 . Указательные типы
- 8.2. Структуры данных
- 8.3. Распределение памяти
- 8.4. Алгоритмы распределения динамической памяти
- 8.5. Упражнения
- Глава 9
- 9.1. Представление вещественных чисел
- 9.2. Языковая поддержка вещественных чисел
- 9.3. Три смертных греха
- Вещественные типы в языке Ada
- 9.5. Упражнения
- Глава 10
- 10.1. Преобразование типов
- 10.2. Перегрузка
- 10.3. Родовые (настраиваемые) сегменты
- 10.4. Вариантные записи
- 10.5. Динамическая диспетчеризация
- 10.6. Упражнения
- Глава 11
- 11.1. Требования обработки исключительных ситуаций
- 11.2. Исключения в pl/I
- 11.3. Исключения в Ada
- 11.5. Обработка ошибок в языке Eiffei
- 11.6. Упражнения
- Глава 12
- 12.1. Что такое параллелизм?
- 12.2. Общая память
- 12.3. Проблема взаимных исключений
- 12.4. Мониторы и защищенные переменные
- 12.5. Передача сообщений
- 12.6. Язык параллельного программирования оссаm
- 12.7. Рандеву в языке Ada
- 12.9. Упражнения
- Глава 13
- 13.1. Раздельная компиляция
- 13.2. Почему необходимы модули?
- 13.3. Пакеты в языке Ada
- 13.4. Абстрактные типы данных в языке Ada
- 13.6. Упражнения
- Глава 14
- 14.1. Объектно-ориентированное проектирование
- В каждом объекте должно скрываться одно важное проектное решение.
- 14.3. Наследование
- 14.5. Объектно-ориентированное программирование на языке Ada 95
- Динамический полиморфизм в языке Ada 95 имеет место, когда фактический параметр относится к cw-типу, а формальный параметр относится к конкретному типу.
- 14.6. Упражнения
- Глава 15
- 1. Структурированные классы.
- 15.1. Структурированные классы
- 5.2. Доступ к приватным компонентам
- 15.3. Данные класса
- 15.4. Язык программирования Eiffel
- Если свойство унаследовано от класса предка более чем одним путем, оно используется совместно; в противном случае свойства реплицируются.
- 15.5. Проектные соображения
- 15.6. Методы динамического полиморфизма
- 15.7. Упражнения
- 5Непроцедурные
- Глава 16
- 16.1. Почему именно функциональное программирование?
- 16.2. Функции
- 16.3. Составные типы
- 16.4. Функции более высокого порядка
- 16.5. Ленивые и жадные вычисления
- 16.6. Исключения
- 16.7. Среда
- 16.8. Упражнения
- Глава 17
- 17.2. Унификация
- 17.4. Более сложные понятия логического программирования
- 17.5. Упражнения
- Глава 18
- 18.1. Модель Java
- 18.2. Язык Java
- 18.3. Семантика ссылки
- 18.4. Полиморфные структуры данных
- 18.5. Инкапсуляция
- 18.6. Параллелизм
- 18.7. Библиотеки Java
- 8.8. Упражнения