Я думаю, что это может быть полезной языковой функцией, и мне было интересно, поддерживают ли ее какие-либо языки.
Идея в том, если у вас есть:
class C
virtual F
statement1
statement2
и
class D inherits C
override F
statement1
statement2
C.F()
К CF () будет применено ключевое слово, такое, что удаление последней строки кода, приведенного выше, приведет к ошибке компилятора, так как он говорит: «Этот метод может быть переопределен, но реализация должна выполняться независимо от того, что».
programming-languages
Аарон Анодид
источник
источник
Ответы:
Да, они делают. Это называется скандинавская модель ОО, она используется, например, в Simula (другая модель ОО, которая широко распространена и считается само собой разумеющейся в настоящее время, - американская модель). В скандинавской модели вы не переопределяете, а задаете подчиненное поведение.
в методе суперкласса foo:
в подклассе 'метод foo:
При вызове метода Foo суперкласса экземпляры, только
some-code-before
иsome-code-after
бывает (INNER
ничего не делает), но если вы звоните Foo Подкласс экземпляры, он делаетsome-code-before
,some-code-in-subclass
а затемsome-code-after
.источник
Ни один из известных мне языков не заставляет вызывать переопределенный метод. Действительно, некоторые языки допускают переопределение методов, которые не могут быть переопределены (например, использование
new
ключевого слова в C #). Однако есть два способа приблизиться к этому.Первый - создать не переопределяемый метод (например, метод, в котором отсутствует
virtual
ключевое слово в C # или метод , содержащийfinal
ключевое слово в Java), который вызывает переопределяемый метод, который нельзя вызвать извне класса (например,protected
в C #, Java или C ++).и
Переопределение классов
C
может свободно переопределятьF
и изменять его поведение, но вызывающие извне класса только получают к нему доступA
.Редактировать: Как уже отмечали другие, это называется шаблоном метода Template .
Второй способ - использовать язык, который обеспечивает предварительные условия и постусловия, указанные в базовом классе, такие как Eiffel или C # с кодовыми контрактами. Это не заставит вызывать базовый класс, но переопределенный метод может быть вынужден выполнять те же операторы. Использование аспектов может также помочь, если язык позволяет аспектам наследоваться.
источник
private
в C ++ :) Херб Саттер объясняет это здесь подробно.На самом деле не является частью языка, но статический анализатор кода FindBugs для Java имеет аннотацию,
OverrideMustInvoke
которую разработчик может добавить к методу и которая заставит FindBugs показать ошибку, если он найдет переопределяющий метод, который не вызывает супер реализацию , Он даже позволяет указать, должен ли вызов быть первым или последним в переопределяющем методе.источник
Требование вызова метода суперкласса является анти-паттерном . Если он не применяется во время компиляции, он подвержен ошибкам, поэтому вы ищете языковую конструкцию, которая его проверяет.
Существует способ, который поддерживается во всех языках ОО: шаблон шаблона . Здесь вы делаете метод суперкласса не переопределяемым, и в нем вы вызываете переопределяемый метод. Затем подкласс может переопределить этот метод для добавления функциональности:
В зависимости от местоположения вызова переопределенного метода, он даже позволяет определить порядок выполнения, который при обычном супер вызове осуществляется по желанию разработчика подкласса.
источник
Самый близкий образец, который я могу придумать, это самоподписанные события. Это немного громоздко, и совсем не интуитивно понятно для кодера, но достигает цели.
источник
Машина «flavors» на Лиспе допускала методы с типом «before», «after» и «around» унаследованным основным методом.
источник
Хотя это не плохая идея в теории, у нее есть отрицательный побочный эффект ограничения моих вариантов при реализации
D
. Например, что если (по какой-то непостижимой причине) удобнее вызывать реализацию суперклассаF
из какого-то другого метода:По вашему сценарию, я предполагаю, что компилятор будет отмечать реализацию
F
inD
, даже если он (косвенно) вызываетC.F()
.По сути, вы описали возможный механизм, помогающий компилятору распознавать, когда
C
нарушается контракт на классы, наследуемые от . Я хочу сказать, что, хотя это здорово, это не должно происходить за счет ограничения того, как я могу реализовать свой подкласс.источник