- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы объектно-ориентированного программирования - Бертран Мейер
Шрифт:
Интервал:
Закладка:
В итоге, как мне известно, проверка системной корректности осталась никем не реализованной. (Другой причиной такого исхода, возможно, послужила сложность самих правил проверки.)
Классовая корректность предполагает проверку, ограниченную классом, и, следовательно, возможна при возрастающей компиляции. Системная корректность предполагает глобальную проверку всей системы, что входит в противоречие с возрастающей компиляцией.
Однако, несмотря на свое имя, фактически можно проверить системную корректность, используя только возрастающую проверку классов (в процессе работы обычного компилятора). Это и будет финальным вкладом в решение проблемы.
Остерегайтесь полиморфных кэтколлов!
Правило Системной Корректности пессимистично: в целях упрощения оно отвергает и вполне безопасные комбинации инструкций. Как ни парадоксально, но последний вариант решения мы построим на основе еще более пессимистического правила. Естественно, это поднимет вопрос о том, насколько реалистичным будет наш результат.
Назад, в Ялту
Суть решения Кэтколл (Catcall), - смысл этого понятия мы поясним позднее, - в возвращении к духу Ялтинских соглашений, разделяющих мир на полиморфный и ковариантный (и спутник ковариантности - скрытие потомков), но без необходимости обладания бесконечной мудростью.
Как и прежде, сузим вопрос о ковариантности до двух операций. В нашем главном примере это полиморфное присваивание: s := b, и вызов ковариантной подпрограммы: s.share (g). Анализируя, кто же является истинным виновником нарушений, исключим аргумент g из числа подозреваемых. Любой аргумент, имеющий тип SKIER или порожденный от него, нам не подходит ввиду полиморфизма s и ковариантности share. А потому если статически описать сущность other как SKIER и динамически присоединить к объекту SKIER, то вызов s.share (other) статически создаст впечатление идеального варианта, но приведет к нарушению типов, если полиморфно присвоить s значение b.
Фундаментальная проблема в том, что мы пытаемся использовать s двумя несовместимыми способами: как полиморфную сущность и как цель вызова ковариантной подпрограммы. (В другом нашем примере проблема состоит в использовании p как полиморфной сущности и как цели вызова подпрограммы потомка, скрывающего компонент add_vertex.)
Решение Кэтколл, как и Закрепление, носит радикальный характер: оно запрещает использовать сущность как полиморфную и ковариантную одновременно. Подобно глобальному анализу, оно статически определяет, какие сущности могут быть полиморфными, однако, не пытается быть слишком умным, отыскивая для сущностей наборы возможных типов. Вместо этого всякая полиморфная сущность воспринимается как достаточно подозрительная, и ей запрещается вступать в союз с кругом почтенных лиц, включающих ковариантность и скрытие потомком.
Одно правило и несколько определений
Правило типов для решения Кэтколл имеет простую формулировку:
Правило типов для Кэтколл
Полиморфные кэтколлы некорректны.
В его основе - столь же простые определения. Прежде всего, полиморфная сущность:
Определение: полиморфная сущность
Сущность x ссылочного (не развернутого) типа полиморфна, если она обладает одним из следующих свойств:
1 Встречается в присваивании x := y, где сущность y имеет иной тип или по рекурсии полиморфна.
2 Встречается в инструкциях создания create {OTHER_TYPE} x, где OTHER_TYPE не является типом, указанным в объявлении x.
3 Является формальным аргументом подпрограммы.
4 Является внешней функцией.
Цель этого определения - придать статус полиморфной ("потенциально полиморфной") любой сущности, которую при выполнении программы можно присоединить к объектам разных типов. Это определение применимо лишь к ссылочным типам, так как развернутые сущности по природе не могут быть полиморфными.
В наших примерах лыжник s и многоугольник p - полиморфны по правилу (1). Первому из них присваивается объект BOY b, второму - объект RECTANGLE r.
Если вы познакомились с формулировкой понятия набора типов, то заметили, насколько пессимистичнее выглядит определение полиморфной сущности, и насколько проще его проверить. Не пытаясь отыскать все всевозможные динамические типы сущности, мы довольствуемся общим вопросом: может данная сущность быть полиморфной или нет? Наиболее удивительным выглядит правило (3), по которому полиморфным считается каждый формальный параметр (если его тип не расширен, как в случае с целыми и т. д.). Мы даже не утруждаем себя анализом вызовов. Если у подпрограммы есть аргумент, то он находится в полном распоряжении клиента, а значит, и полагаться на указанный в объявлении тип нельзя. Это правило тесно связано с повторным использованием - целью объектной технологии, - где любой класс потенциально может быть включен в состав библиотеки, и будет многократно вызываться различными клиентами.
Характерным свойством этого правила является то, что оно не требует никаких глобальных проверок. Для выявления полиморфности сущности достаточно просмотреть текст самого класса. Если для всех запросов (атрибутов или функций) сохранять информацию об их статусе полиморфности, то не приходится изучать даже тексты предков. В отличие от отыскания наборов типов, можно обнаружить полиморфные сущности, проверяя класс за классом в процессе возрастающей компиляции.
Как было сказано при обсуждении наследования, подобный анализ может также представлять ценность при оптимизации кода.Вызовы, как и сущности, могут быть полиморфными:
Определение: полиморфный вызов
Вызов является полиморфным, если его цель полиморфна.
Оба вызова в наших примерах полиморфны: s.share (g) ввиду полиморфизма s, p.add_ vertex (...) ввиду полиморфизма p. Согласно определению, только квалифицированные вызовы могут быть полиморфны. (Придав неквалифицированному вызову f (...) вид квалифицированного Current.f (...), мы не меняем суть дела, поскольку Current, присвоить которому ничего нельзя, не является полиморфным объектом.)
Далее нам потребуется понятие Кэтколла, основанное на понятии CAT. (CAT - это аббревиатура Changing Availability or Type - изменение доступности или типа). Подпрограмма является CAT подпрограммой, если некоторое ее переопределение потомком приводит к изменениям одного из двух видов, которые, как мы видели, являются потенциально опасными: изменяет тип аргумента (ковариантно) или скрывает ранее экспортировавшийся компонент.
Определение: CAT-подпрограммы
Подпрограмма называется CAT-подпрограммой, если некоторое ее переопределение изменяет статус экспорта или тип любого из ее аргументов.
Это свойство опять-таки допускает возрастающую проверку: любое переопределение типа аргумента или статуса экспорта делают процедуру или функцию CAT-подпрограммой. Отсюда следует понятие Кэтколла: вызова CAT-подпрограммы, который может оказаться ошибочным.
Определение: Кэтколл
Вызов называется Кэтколлом, если некоторое переопределение подпрограммы сделало бы его ошибочным из-за изменения статуса экспорта или типа аргумента.
Созданная нами классификация позволяет выделять специальные группы вызовов: полиморфные и кэтколлы. Полиморфные вызовы придают выразительную мощь объектному подходу, кэтколлы позволяют переопределять типы и ограничивать экспорт. Используя терминологию, введенную ранее в этой лекции, можно сказать, что полиморфные вызовы расширяют полезность (usefulness), кэтколлы - используемость(usability).
Вызовы share и add_vertex, рассмотренные в наших примерах, являются кэт-коллами. Первый осуществляет ковариантное переопределение своего аргумента. Второй экспортируется классом RECTANGLE, но скрыт классом POLYGON. Оба вызова также и полиморфны, а потому они служат прекрасным примером полиморфных кэтколлов. Они являются ошибочными согласно правилу типов Кэтколл.
Оценка
Прежде чем мы сведем воедино все, что узнали о ковариантности и скрытии потомком, вспомним еще раз о том, что нарушения корректности систем возникают действительно редко. Наиболее важные свойства статической ОО-типизации были обобщены в начале лекции. Этот впечатляющий ряд механизмов работы с типами совместно с проверкой классовой корректности, открывает дорогу к безопасному и гибкому методу конструирования ПО.
