Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4086 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Дополнительный материал 2:

Универсальность и (versus) наследование

< Дополнительный материал 1 || Дополнительный материал 2: 123456

Ключевые концепции

  • Универсальность и наследование направлены на повышение гибкости программных модулей.
  • Универсальность - статическая техника, применимая в объектном и не объектном контексте, позволяет определять модули с типами в качестве параметров.
  • Есть две формы универсальности: неограниченная, не налагающая никаких требований на параметры и ограниченная, требующая от параметра-типа поддержки определенных операций.
  • Наследование позволяет нарастающее конструирование модуля путем расширения и специализации. Наследование открывает дорогу полиморфизму и динамическому связыванию.
  • Реализовать наследование с помощью универсальности не представляется возможным.
  • Чистое наследование может использоваться для эмуляции универсальности, но за счет утяжеления выражений, потери производительности и трудностей с типами.
  • Удачным компромиссом является комбинирование всей мощи наследования и переопределения с универсальностью, по меньшей мере, в его неограниченной форме. Это достигается разрешением классам иметь родовые параметры.
  • Крайне желательно обеспечить ограниченную универсальность, которая может быть построена на основе понятия согласованности типов, следующего, в свою очередь, из наследования. Неограниченная универсальность в этом случае представляет собой частный случай, в котором универсальный класс ANY выступает в роли ограничения.
  • Результирующая конструкция получается элегантной и минимальной.

Библиографические замечания

Материал для этой лекции основан на докладе на первой конференции OOPSLA [М. 1986]. Комбинация множественного наследования с ограниченной и неограниченной универсальностью предложена также в языке Trellis [Schaffert 1986].

Упражнения

УB.1 Искусственные якоря

Искусственный якорь anchor объявлен как атрибут класса MATRIX и потому требует в период выполнения выделения для экземпляров класса дополнительной (небольшой) памяти. Возможно ли избежать этих потерь, объявив якорь однократной функцией, чье тело может быть пустым, так как фактически она никогда не будет вычисляться? ( Подсказка: рассмотрите правила типов.)

УB.2 Бинарные деревья и бинарные деревья поиска

Напишите универсальное "бинарное дерево"-класс BINARY_TREE. Бинарное дерево задается информацией в корне дерева и двумя возможными поддеревьями, левым и правым. Затем рассмотрите "бинарное дерево поиска", для всех узлов которого выполняется следующее условие: информация в узле больше или равна информации в корне левого поддерева, но меньше информации в корне правого поддерева. Это означает задание полного порядка на "информациях". Напишите класс BINARY_SEARCH_TREE, реализующий это понятие как потомка BINARY_TREE. Сделайте класс универсальным, насколько это возможно. Клиенты должны использовать класс для произвольных типов, задающих информацию и специфическое отношение порядка.

УB.3 Более просто используемые матрицы

Добавьте в последнюю версию класса MATRIX две функции - для доступа и модификации элементов, которые в противоположность item и put будут позволять клиентам манипулировать матрицами типа MATRIX [G] в терминах элементов типа G, а не типа RING_ELEMENT [G].

УВ.4 Полная реализация очередей

Расширьте пример с очередью, определив отложенный класс QUEUE, дополнив класс этого приложения (называемый теперь ARRAYED_QUEUE, наследуемый от QUEUE и ARRAY, с подходящими постусловиями). Добавьте класс LINKED_QUEUE для реализации связного списка (основанный на наследовании от LINKED_LIST и QUEUE ).

< Дополнительный материал 1 || Дополнительный материал 2: 123456