OberonCore
https://forum.oberoncore.ru/

Супер-вызовы
https://forum.oberoncore.ru/viewtopic.php?f=29&t=614
Страница 1 из 1

Автор:  Калям [ Четверг, 16 Август, 2007 17:22 ]
Заголовок сообщения:  Супер-вызовы

В "Сообщении о языке" утверждается, что супер-вызовы - средство устаревшее, а следовательно нужно стараться не использовать его. Однако в том же "Сообщении" есть пример, где используется именно супер-вызов (глава 10.2 Методы). Также, насколько помню, на форуме даже говорили, что они сплошь и рядом в самОй реализации BB. Кто может объяснить такое положение?

Теперь о конкретной проблеме, которую ставит отказ от супер-вызовов: как предлагается обходиться без них?

Вот пример:

есть связанная переопределяемая процедура (метод), код которой - 1000 строк. В некотором потомке потребовалось переопределить её, причём добавляемая функциональность мала, скажем 50 строк кода.

Если не использовать супер-вызов, то, фактически, придётся заново реализовывать те же самые 1000 строк в этой переопределённой процедуре (+50 новых), что, согласитесь, нерационально. Как предлагается поступать?

Автор:  Илья Ермаков [ Четверг, 16 Август, 2007 19:15 ]
Заголовок сообщения:  Re: Супер-вызовы

Супервызовов в исходниках среды довольно немного. Точно так же, как относительно немного и наследования реализации - только в заготовках Framework, и то - типы с реализацией всё равно сделаны абстрактными.

Проблема наследования реализации много раз обсуждалась - в компонентном ПО возникают проблемы: хрупкого базового класса и т.п., это описано у Пфистера в "Компонентом ПО". В системном программировании следует избегать использования наследования реализации, использовать только гомогенные иерархии наследования (абстрактный тип-интерфейс - конкретное расширение-реализация, неэкспортируемое). И так не только в КП, такой подход является основой многих ООП-паттернов (в частности, рекомендуется в книге Гаммы и др. "Паттерны объектно-ориентированного проектирования", построенной на Smalltalk и С++, живым примером которой является, тем не менее, BlackBox).

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

Примеры таких решений - паттерны Model-View-Controller, фирменно-блэкбоксовый Carrier-Rider-Mapper.
А в подсистеме Text вообще выделено больше типов, чем модель-отображение-диспетчер: ещё и Mappers, Setters - отвечающий за вёрстку на странице, Rulers... Всегда достаточно переписать только один из этих типов, да и то не обязательно целиком - можно просто обернуть стандартную реализацию, заменяя некоторые вызовы, а остальные делегируя обёрнутому объекту...

Автор:  Илья Ермаков [ Четверг, 16 Август, 2007 19:30 ]
Заголовок сообщения:  Re: Супер-вызовы

Однако если всё-таки используется наследование реализации... Например, если пишется "каркас-заготовка", или решается прикладная задача, где иерархии идут от самой предметной области...

То супервызовы всё равно не нужны, вместо них лучше использовать "версионированные методы".
Пример в ББ - тип Containers.Container. Возьмём его процедуру HandleCtrlMsg.
Она имеет реализацию. Более того, она предназначена для расширения в потомках. Однако - она не EXTENSIBLE! Как так? Очень просто.
Container имеет другую процедуру - HandleCtrlMsg2, объявленную как EMPTY (т.е. пустышку) и с экспортом "-" - т.е. только для реализации.
HandleCtrlMsg в нужном месте вызывает HandleCtrlMsg2.

В итоге - в типах-расширениях мы определяем HandleCtrlMsg2. Супервызова не используем - вызывать нечего... Наоборот, базовая процедура вызывает нас, в тот момент, когда считает нужным.

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

Автор:  Wlad [ Четверг, 16 Август, 2007 22:01 ]
Заголовок сообщения:  Re: Супер-вызовы

Калям писал(а):
есть связанная переопределяемая процедура (метод), код которой - 1000 строк.

Ой! Вы меня испугали! :о)
Это что-то - из ряда-вон - больше трёх экранов на процедуру!

Автор:  Калям [ Четверг, 16 Август, 2007 22:15 ]
Заголовок сообщения:  Re: Супер-вызовы

Владимир Лось писал(а):
Это что-то - из ряда-вон - больше трёх экранов на процедуру!

Пример гипотетический.

Автор:  Wlad [ Четверг, 16 Август, 2007 22:46 ]
Заголовок сообщения:  Re: Супер-вызовы

Калям писал(а):
Владимир Лось писал(а):
Это что-то - из ряда-вон - больше трёх экранов на процедуру!

Пример гипотетический.

Гипотетически автор закладывается на расширение при проектировании (примерно, как скзал Илья и как позволяет язык).
Иначе он - сам себе злобный Буратино!

Автор:  Сергей Губанов [ Пятница, 17 Август, 2007 13:25 ]
Заголовок сообщения:  Re: Супер-вызовы

Илья Ермаков писал(а):
...(хе-хе, ни в одном другом языке такого нет :-) )...


В C# есть комбинация модификаторов protected internal - Access is limited to the current assembly or types derived from the containing class. Это примерно тоже что и экспорт только для реализации Component Pascal.

Автор:  Александр Ильин [ Пятница, 17 Август, 2007 16:14 ]
Заголовок сообщения:  Re: Супер-вызовы

Сергей Губанов писал(а):
Access is limited to the current assembly or types derived from the containing class.

А derived class может этот метод вызывать? В BlackBox не может.

Автор:  Сергей Губанов [ Пятница, 17 Август, 2007 16:40 ]
Заголовок сообщения:  Re: Супер-вызовы

Александр Ильин писал(а):
Сергей Губанов писал(а):
Access is limited to the current assembly or types derived from the containing class.

А derived class может этот метод вызывать? В BlackBox не может.


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

Автор:  Илья Ермаков [ Пятница, 17 Август, 2007 18:43 ]
Заголовок сообщения:  Re: Супер-вызовы

И угадайте с трёх раз, кто принёс "факел знаний" о безопасных режимах ООП в компонентном программировании в Микрософт.. :-) Уверен, что ни кто иной, как Шиперски!

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/