Читаем Основы объектно-ориентированного программирования полностью

Разрешим объявления вида like s лишь тогда, когда s описано как anchor. Изменим правила совместимости так, чтобы гарантировать: s и элементы типа like s могут присоединяться (в присваиваниях или передаче аргумента) только друг к другу.

В исходном варианте правила существовало понятие опорно-эквивалентных элементов. При новом подходе опорно-эквивалентными должны быть как правая, так и левая часть любого присваивания, в котором участвует опорная или закрепленная сущность.

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

r (u: Y) ...

тогда как у класса C - родителя D это выглядело

r (u: X) ...

где Y соответствовало X, то теперь переопределение компонента r будет выглядеть так:

r (u: like your_anchor) ...

Остается только в классе D переопределить тип your_anchor.

Это решение проблемы ковариантности - полиморфизма будем называть подходом Закрепления (Anchoring). Более аккуратно следовало бы говорить: "Ковариация только через Закрепление". Свойства подхода привлекательны:

[x]. Закрепление основано на идее строгого разделения ковариантных и потенциально полиморфных (или, для краткости, полиморфных) элементов. Все сущности, объявленные как anchor или like some_anchor ковариантны; прочие-полиморфны. В каждой из двух категорий допустимы любые присоединения, но нет сущности или выражения, нарушающих границу. Нельзя, например, присвоить полиморфный источник ковариантной цели.

[x]. Это простое и элегантное решение нетрудно объяснить даже начинающим.

[x]. Оно полностью устраняет возможность нарушения системной корректности в ковариантно построенных системах.

[x]. Оно сохраняет заложенную выше концептуальную основу, в том числе понятия ограниченной и неограниченной универсальности. (В итоге это решение, по-моему, предпочтительнее типовых переменных, подменяющих собой механизмы ковариантности и универсальности, предназначенных для решения разных практических задач.)

[x]. Оно требует незначительного изменения языка, - добавляя одно ключевое слово, отраженное в правиле соответствия, - и не связано с ощутимыми трудностями в реализации.

[x]. Оно реалистично (по крайней мере, теоретически): любую ранее возможную систему можно переписать, заменив ковариантные переопределения закрепленными повторными объявлениями. Правда, некоторые присоединения в результате станут неверными, но они соответствуют случаям, которые могут привести к нарушениям типов, а потому их следует заменить попытками присваивания и разобраться в ситуации во время выполнения.

Казалось бы, дискуссию можно на этом закончить. Так почему же подход Закрепления не полностью нас устраивает? Прежде всего, мы еще не касались проблемы скрытия потомком. Кроме этого, основной причиной продолжения дискуссии является проблема, уже высказанная при кратком упоминании типовых переменных. Раздел сфер влияния на полиморфную и ковариантную часть, чем-то похож на результат Ялтинской конференции. Он предполагает, что разработчик класса обладает незаурядной интуицией, что он в состоянии для каждой введенной им сущности, в частности для каждого аргумента раз и навсегда выбрать одну из двух возможностей:

[x]. Сущность является потенциально полиморфной: сейчас или позднее она (посредством передачи параметров или путем присваивания) может быть присоединена к объекту, чей тип отличается от объявленного. Исходный тип сущности не сможет изменить ни один потомок класса.

[x]. Сущность является субъектом переопределения типов, то есть она либо закреплена, либо сама является опорным элементом.

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

При таком подходе переопределение типов и скрытие потомком - своего рода "предохранительный клапан", дающий возможность повторно использовать существующий класс, почти пригодный для достижения наших целей:

Перейти на страницу:

Похожие книги

«Ага!» и его секреты
«Ага!» и его секреты

Вы бы не хотели, скажем, изобрести что-то или открыть новый физический закон, а то и сочинить поэму или написать концерт для фортепьяно с оркестром?Не плохо бы, верно? Только как это сделать? Говорят, Шиллер уверял, будто сочинять стихи ему помогает запах гнилых яблок. И потому, принимаясь за работу, всегда клал их в ящик письменного стола. А физик Гельмгольц поступал иначе. Разложив все мысленно по полочкам, он дожидался вечера и медленно поднимался на гору лесной дорогой. Во время такой прогулки приходило нужное решение.Словом, сколько умов, столько способов заставить мозг работать творчески. А нет ли каких-то строго научных правил? Одинаковы ли они для математиков, биологов, инженеров, поэтов, художников? Да и существуют ли такие приемы, или каждый должен полагаться на свои природные способности и капризы вдохновения?Это тем более важно знать, что теперь появились «электронные ньютоны» — машины, специальность которых делать открытия. Но их еще нужно учить.Решающее слово здесь принадлежит биологам: именно они должны давать рецепты инженерам. А биологи и сами знают о том, как мы думаем, далеко не все. Им предстоит еще активнее исследовать лабораторию нашего мышления.О том, как ведутся эти исследования, как постепенно «умнеют» машины, как они учатся и как их учат, — словом, о новой науке эвристике рассказывает эта книга.

Елена Викторовна Сапарина

Зарубежная компьютерная, околокомпьютерная литература