Что означает повторное введение и переопределение директив в Delphi? - PullRequest
26 голосов
/ 12 апреля 2009

В чем разница между директивами override и reintroduce? И когда мне не следует использовать ключевое слово inherited в переопределенных методах?

Ответы [ 4 ]

45 голосов
/ 12 апреля 2009

Ссылка на ответ Джима, который был превосходным, кстати, описывает только то, когда и где использовать директивы. Другая часть ответа - зачем они нужны? Многие языки прекрасно обходятся без них, верно? При разработке аспектов языка Delphi Object Pascal ООП (объектно-ориентированное программирование) было в мейнстриме в течение нескольких лет. В течение этого времени было замечено, что использование многих языков, в которых были приняты эти концепции (Turbo Pascal, C ++ и т. Д.) Для разработки прикладных сред, страдало от того, что я назвал проблемой «версии 2.».

Предположим, вы разработали потрясающую среду, используя язык X, и выпустили ее как версию 1. Ваши пользователи были в восторге от всего, что он мог сделать, и он стал активно использоваться. Встретившись с успехом, вы решили выпустить версию 2 с еще большей удивительностью. Вы специально убедились, что он полностью обратно совместим. Внезапно ваши пользователи начали сообщать о странном поведении. Их собственные виртуальные методы вызывались в странные времена. Многие сообщили, что их старый код не будет компилироваться с новой версией. Странный. Все те же объекты, методы и функциональность все еще остались. Все, что вы сделали, это добавили несколько виртуальных методов к некоторым базовым классам, несколько новых типов объектов и некоторые новые дополнительные функции. Что случилось?

Директивы override и reintroduce служат для устранения этой проблемы, требуя, чтобы для фактического override виртуального метода вы использовали директиву override вместо виртуальной директивы. Если вам случится представить свой собственный виртуальный метод, имя которого совпадает с именем одного из виртуальных методов ваших предков, компилятор теперь предупредит вас, но все равно будет поступать правильно. В этом случае повторное введение не только подавляет это предупреждение, но и служит для документирования в источнике, который вы намеревались сделать.

Без директив переопределения и повторного ввода вы не сможете постоянно развивать свою среду, не опасаясь взломать всех своих пользователей. И если бы вашим пользователям приходилось вносить огромные изменения каждый раз, когда выпускается новая версия, они не хотели бы принимать новую версию. Наконец, использование «переопределения» также позволяет конструктору каркасов изменять тип виртуального в предках, не нарушая пользовательский код. Например, в Delphi многие методы помечены как «динамические», что является формой поиска полиморфизма на основе таблицы во время выполнения. Он работает не так быстро, как обычный виртуальный, поэтому он обычно используется для методов, которые редко переопределяются и / или являются реакциями на действия пользователя, когда дополнительные издержки никогда не замечаются. Предположим, что в V1 фреймворка метод был помечен как «динамический», но на практике он был переопределен и вызван больше, чем вы предполагали. В V2 вы можете изменить его на «виртуальный», не опасаясь взлома пользовательского кода.

Язык Object Pascal в Delphi - не единственный язык, который распознает эту проблему. C # требует использования директивы override по той же самой причине. Комитет по стандартам C ++ наконец-то осознает проблему и модифицирует язык для ее поддержки ... вроде. В C ++, если имя метода и список параметров совпадают с виртуальным предком, это переопределение (даже если вы не говорите «виртуальный» для потомка!). Для грядущего нового стандарта C ++, если вы укажете «virtual» и сигнатуры не будут совпадать, тогда это новый виртуальный метод, представленный в текущем классе. Если есть совпадение подписи с предком и автор не не намеревался переопределить, то ключевое слово "new" используется, чтобы сообщить компилятору, что это new virtual для этот класс.

11 голосов
/ 12 апреля 2009

Директива override используется для переопределения виртуальных методов в унаследованных классах.

Директива reintroduce используется для объявления метода с тем же именем, что и в суперклассе, но с другими параметрами.

6 голосов
/ 12 апреля 2009

А когда мне не следует использовать унаследованное ключевое слово в переопределенных методах?

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

В качестве примера представьте, что вы хотите полностью переопределить унаследованную функцию ApplyDiscount, но кто-то жестко закодировал процент скидки в классе предков. Если вы вызываете унаследованный ApplyDiscount, он переопределит ваш код или вычислит значение, которое вы затем переопределите; в этом случае вы можете просто не звонить по наследству и применять скидку самостоятельно.

(Это надуманный пример, поэтому, если кто-то может придумать лучший, добавьте его.)

1 голос
/ 13 апреля 2009

Есть много обстоятельств, когда вы не хотите вызывать унаследованный в переопределенном методе.

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

Некоторые из моих классов имеют реализацию по умолчанию, которая работает в большинстве случаев. Метод переопределяется только для замены по умолчанию, и нет необходимости вызывать значение по умолчанию.

Например, функция GST (= налог с продаж) моего базового финансового объекта возвращает 12,5% от суммы ExGst, а IncGst возвращает ExGst + GST.

В моих объектах компенсации дохода GST всегда возвращает 0, поэтому нет необходимости вызывать унаследованную функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...