Implicit vs Explicit Call to inherited

When overriding a method, you have the choice to call the ancestor method implicitly with the inherited keyword alone or with also the method name and its parameters if any.

Does it make a difference? Why choose one or the other?

procedure TForm2.AfterConstruction;
begin
  inherited;
  MessageBox(0, 'Hello!', 'Test', MB_ICONINFORMATION or MB_OK);
end;

vs

procedure TForm2.AfterConstruction;
begin
  inherited AfterConstruction;
  MessageBox(0, 'Hello!', 'Test', MB_ICONINFORMATION or MB_OK);
end;

Compiled code

It does not matter for the compiler as it knows the proper ancestor’s method to call and how to pass the parameter directly. You can verify from the CPU View:

004A3AFE 0000             add [eax],al
004A3B00 0200             add al,[eax]
004A3B02 8BC0             mov eax,eax
Unit2.pas.30: inherited;
004A3B04 E80B35FFFF       call TCustomForm.AfterConstruction
Unit2.pas.33: MessageBox(0, 'Hello!', 'Test', MB_ICONINFORMATION or MB_OK);
004A3B09 6A40             push $40
004A3B0B 68203B4A00       push $004a3b20
004A3B10 682C3B4A00       push $004a3b2c
004A3B15 6A00             push $00
004A3B17 E8707EF6FF       call MessageBox
Unit2.pas.34: end;
004A3B1C C3               ret

vs

004A3AFE 0000             add [eax],al
004A3B00 0200             add al,[eax]
004A3B02 8BC0             mov eax,eax
Unit2.pas.31: inherited AfterConstruction;
004A3B04 E80B35FFFF       call TCustomForm.AfterConstruction
Unit2.pas.33: MessageBox(0, 'Hello!', 'Test', MB_ICONINFORMATION or MB_OK);
004A3B09 6A40             push $40
004A3B0B 68203B4A00       push $004a3b20
004A3B10 682C3B4A00       push $004a3b2c
004A3B15 6A00             push $00
004A3B17 E8707EF6FF       call MessageBox
Unit2.pas.34: end;
004A3B1C C3               ret

Source code

Code completion creates the method skeleton with inherited only, while it’s mostly with the explicit method signature in the VCL code, esp. for nontrivial cases.

Let’s put aside the unavoidable case when you need to call the base method with different parameters.

So, why bother typing the longer method signature?

Because code ultimately spend most of its life in maintenance mode: it’s write once, read many times. And remember, it’s harder to read code than to write it.

  • It avoids dumb copy’n’haste.
  • It makes code navigation easier, by allowing “Ctrl-click” or “Right Menu|Find Declaration” to jump directly to the exact ancestor method, without working one’s way up in the class hierarchy.
  • I find it easier to have all the information on the line I’m reading than scrolling up to look at the signature.
  • … and even more so in the CPU View.

Please do the programmer who comes after you a favor, add the extra signature.
After all, it might be you…

This entry was posted in Coding standard, Delphi and tagged , , . Bookmark the permalink.

13 Responses to Implicit vs Explicit Call to inherited

  1. Thanks for writing this up. I’ve long held the opinion that “naked inherited is evil,” for all the reasons you mentioned and one more: because it can silently introduce bugs if the inherited method you’re trying to call doesn’t exist. This happened to TObjectList<T> in Delphi 2009, for example. One of the constructors tried to call inherited; when there was no constructor in TList<T> with the same signature. Instead of a compiler error, it became a silent no-op and some important initialization in the base class didn’t take place.

    • François Gaillard says:

      Thanks Mason for mentioning this reason and sharing this example.
      It reminds me that I also forgot to mention the unnecessary inherited added to all event handlers “just in case” when descending from a Form.

  2. Pingback: TURBU Tech » Blog Archive » New blogs to watch

  3. Jolyon Smith says:

    “It avoids dumb copy’n’haste.”

    Surely it just creates a different flavour of Copy ‘n Haste… an explicit call to “inherited ‘explicit signature'” copied from one method into another risks creating a call to completely the wrong method.

    Other than that, all other reasons are good, with the caveat that although it makes code easier to maintain, it also creates more code to BE maintained (e.g. if you change parameter names and the refactoring tools are having one of their “moments” and refusing to work correctly or at all leaving you to do the heavy lifting yourself).

    • François Gaillard says:

      There’s no way to prevent copying garbage and just dumping it in the method anyway, but at least there is some chance to see that it may be wrong.
      Also, generally you cannot just copy from the signature above:

      procedure TScrollingWinControl.CreateParams(var Params: TCreateParams);
      begin
        inherited CreateParams(Params);
      

      And I’m with you on the idea of creating LESS code that has to be maintained, but not at the expense of readability.

  4. Rodrigo Ruz says:

    Hi François, good article, I’ve seen to many times in StackOverflow.Com, I had no idea that you had a blog. see you. 😉

    try to register you blog here http://delphifeeds.uservoice.com/forums/14264-feedback to be listed in delphifeeds.com

  5. Rodrigo Ruz says:

    oops, i just saw your blog already registered in http://delphifeeds.uservoice.com/forums/14264-feedback/suggestions/1083289-http-fgaillard-com-?ref=title, i just vote for him, hopefully soon be included in delphifeeds.com 😉

  6. Uli Gerhardt says:

    IIRC it makes a difference in message handlers (eg procedure WMPaint(…); message WM_PAINT;). A call to a non-existing inherited method via the naked inherited is ignored by the compiler while inherited WMPaint yields an error.

  7. In addition to this: what if both methods are a function in stead of a procedure? Does the named “inherited;” assign the function result?

    I’m all for explicitness: it makes things clear, and saves a lot of time in your 80+% of maintenance that you do as a software developer.

    –jeroen

  8. Andrea Raimondi says:

    Oh I hate “inerited” without anything else as well, unless there is absolutely no chance to get it the wrong way – such as in component constructors, AfterConstruction and similar. I always use the extended inherited form when it comes to functions because I might be calling the inherited function with different parameter values. If you’re
    wondering what’s the use of this, consider default paramters that you might want to
    give another value to.

    I think I came to this “compromise” because I tend to write very small routines, like, uhm, less than 25 lines of code 🙂 and tend to re-use stuff and use inheritance and composition a lot. Couple this with extensive purpouse comments and you can see why it’s an acceptable compromise 🙂

    If you think that after all comments aren’t mantained – well, I also tend to not touch what has been “frozen” unless I either have at least three good reasons to do so or I hit a bug.
    Same reason I don’t do a lot of unit testing: when you have plenty of comments, small routines and actually *DO USE* your application during development, chances to not hit a prominent bug are very low. Extremely low. Nastier ones or corner cases will not be probably be covered by tests anyway and/or won’t show up in average use, even though I have been known to add NINETEEN fields to a table creation dialog just to see if it flickered 🙂 (I have done it in a way that mimicks a grid without actually being one 🙂 ).

    Most developers tend to do very little testing: they just see if it compiles, runs and if the most common use case works. They don’t actually try and use it 🙂 That’s imho a very bad programming practice and the worst possible debug method.

    Regards,

    Andrew

  9. Jørn E. Angeltveit says:

    I don’t think it is possible to implicitly inherit functions in Delphi. AFAIK all functions must be explicitly inherited. The main reason is probably because the compiler generates a no-op when the ancestor method doesn’t exist. The statement “Result := inherited;” could therefore end up with an unassigned Result and no run-time warning.

    Remember also that “the cases where the ancestor method doesn’t exist” includes the cases where the ancestor method is abstract, too.

  10. See http://hallvards.blogspot.com/2006/03/virtual-methods-and-inherited.html

    There are indeed differences between the implicit and explicit inherited calls. I think (and AFAIK, some people in Embarcadero agree here), that the implicit call is to be preferred. Not because it is less typing, but because it shows more resilient behaviour. That this behaviour is different from the normal function call shows the intent of the compiler builders that this should be used, IMO.

    • François Gaillard says:

      Actually, your points illustrate why I don’t think it should be used, as it allows developers to make a call not knowing what the compiler will actually give them, especially if the base class changes without the knowledge of the descending classes user/developer.

      The explicit call forces the contract with the base class (and the compiler). If something changes, you’ll know it.
      Code has to be readable (and maintainable) by humans; anything that obfuscate it or make it less obvious or less consistent (functions, out params), or can stealthily alter its semantics, is to be used with extreme caution. Experience seems to indicate that it always lead to some bugs that are harder to spot from code reading.

      Unless you are writing a closed library that people cannot modify, or even read the code, and that you guarantee to work, I maintain it’s better to be explicit…

Leave a Reply to François Gaillard Cancel reply

Your email address will not be published. Required fields are marked *