What is the meaning of the reintroduce and override directives in Delphi?
Asked Answered
S

4

30

What is the difference between the override and reintroduce directives? And when should I not use the inherited keyword in overridden methods?

Singlebreasted answered 12/4, 2009 at 12:57 Comment(1)
#54306Ernest
T
50

The reference to Jim's answer, which was excellent BTW, only described the when and where to use the directives. Another part of the answer is why are they needed anyway? Many languages get along just fine without them, right? When designing aspects of the Delphi Object Pascal Language, OOP (Object Oriented Programming) had been in the mainstream for several years. During this time it was observed that using many of the languages that had adopted those concepts (Turbo Pascal, C++, etc..) to develop application frameworks suffered from what I called the "version 2" problem.

Suppose you developed an awesome framework using language X and released it as version 1. Your users raved at all it could do and it became heavily used. Flush with success, you decide to release version 2 with even more awesomeness. You specifically made sure it was fully backward compatible. Suddenly, you users started reporting strange behaviors. Their own virtual methods were being called at strange times. Many reported that their old code would not compile with the new version. Strange. All the same objects, methods, and functionality still remained. All you did was add a few virtual methods to some base classes, some new object types, and some new optional functionality. What happened?

The override and reintroduce directives serve to eliminate this problem by requiring that in order to actually override a virtual method you must use the override directive in place of the virtual directive. If you happen to introduce your own virtual method that has the same name as one of your ancestors' virtual methods, the compiler now warns you, but will still do the right thing. In this case, using reintroduce, not only suppresses that warning, it also serves to document in the source you intended to do that.

Without the override and reintroduce directives, you would not be able to continually evolve your framework without fear of breaking all your users. And if your users had to make massive modifications every time a new version is released, then they would be loathe to adopt the new version. Finally, using "override" also allows the framework designer to change the type of virtual in the ancestors without breaking user code. For instance, in Delphi many methods are marked "dynamic" which is a table-based runtime method lookup form of polymorphism. It's doesn't perform quite as fast as a regular virtual so it is usually used for methods that are rarely overridden and/or are responses to user actions where the extra overhead is never noticed. Suppose in V1 of the framework a method was marked "dynamic" but in practice it ended up being overridden and called more than you intended. In V2, you could change it to "virtual" without fear of user's code being broken.

Delphi's Object Pascal language isn't the only language to recognize this problem. C# requires the use of an "override" directive for the exact same reason. The C++ standards committee is finally recognizing the problem and are modifying the language to support it... sort of. In C++, if a method's name and parameter list matches an ancestor's virtual, then it is an override (even if you don't say "virtual" on the descendant!). For the upcoming new C++ standard, if you specify "virtual" and the signatures don't match then it is a new virtual method introduced on current class. If there is a signature match with the ancestor and the writer didn't intend to override, then the "new" keyword is used to tell the compiler that this is a new virtual for this class.

Tendency answered 12/4, 2009 at 17:53 Comment(3)
FWIW, Wirth also had an explicit override keyword in his/Apple's Object Pascal (for the Mac), very likely for the same reason. And MS QuickPascal had it too. But neither had a reintroduce.Geum
I'm afraid your answer isn't (and also wasn't that time, 2009) true about the usage of new in C++, but the Delphi part is very informative. Thanks for completing the override story I already knew.Xenomorphic
@Wolf, You're right as far as the ratified standard. It was part of a proposal which never actually made it into the spec. I had attended some C++ ISO committee meetings and there was some discussion of this. At least that's how I recall it. I'm perfectly willing to be wrong about that since it was 10 years ago.Tendency
V
11

The override directive is used to override virtual methods in inherited classes.

The reintroduce directive is used to declare a method with the same name as in the super class, but with different parameters.

Valenti answered 12/4, 2009 at 15:46 Comment(2)
reintroduce is only needed if the method (with the same parameters) in the super class is virtual. If it is not virtual there is no need for "reintroduce" because the super class's method will be hidden anyway.Ferriferous
You should better strike out the part but with different parameters.Xenomorphic
A
6

And when should I not use the inherited keyword in overridden methods?

Basically, the answer is when you don't wish the inherited method to execute. Be careful though as not allowing an inherited method to run may break functionality of an inherited object in a undesirable way, so make sure you are not introducing any unintended side effects.

As an example, imagine you wish to fully override an inherited function called ApplyDiscount, but someone has hardcoded the discount percentage into the ancestor class. If you call the inherited ApplyDiscount it will override your code or calculate a value you will then override; in this case you could just not call inherited and apply the discount yourself.

(This is a contrived example so if someone can think of a better one please add it.)

Assembled answered 12/4, 2009 at 18:22 Comment(0)
C
1

There are many circumstances where you don't want to call inherited in an overridden method.

In some libraries that I use, the base method throws an error (ENotImplimented or similar). Obviously in that case you don't want to call inherited or your code would also throw the error.

Some of my classes have a default implementation that works in the majority of cases. The method is only overridden to replace the default, and there is no need to call the default.

For example, the GST function (= sales tax) on my base financial object returns 12.5% of the ExGst amount and IncGst returns ExGst + GST.

On my Income Compensation objects, GST always returns 0, so there is no need to call the inherited function.

Carencarena answered 12/4, 2009 at 21:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.