10

I have a class that descents from TObject, if I do not call the parent method, is it bad? I ask because when looking at TObject.Create/Destroy, they do nothing.

That's why we override/expose them ourselves.

There's no code example, I just want to make sure.

Jesse
  • 8,605
  • 7
  • 47
  • 57

3 Answers3

17

The most common behaviour is to call inherited. So if I explicitly do not want the inherited behaviour, I do not call inherited. Otherwise, I do. If the inherited behaviour is a no-op like TObject.Create/Destroy, I still call inherited.

Note also that the situtation for constructors and destructors is perhaps a little different than for other methods. It's exceptionally rare that you would need to skip a call to the inherited method. I cannot think of an example. Invariably constructors are creating and destroying other objects, so how could you contemplate skipping that?

I know that some authors write code that omits inherited when deriving directly from TObject, because they know that the implementation in TObject does nothing. I do not like that and to me it is a mistake to do that. The implementation details of TObject should not be leaking into derived classes.

I'm pretty sure that TObject.Create/Destroy will always be no-ops. If Embarcadero changed that then so much code would break. But what about one of your classes. Suppose you have a class derived from TObject. And then you have another class derived from that:

TMyClass1 = class
  ....
end;

TMyClass2 = class(TMyClass)
  ....
end;

You have no constructor for TMyClass1 and a constructor for TMyClass2 that looks like this:

constructor TMyClass2.Create;
begin
  // no need to call inherited, it's a no-op
  FMyObj := TBlahBlah.Create;
end;

Then one day you modify the TMyClass1 constructor to do something. Now TClass2 is broken. So, I would never ever omit a call to inherited because that call does nothing.

The situation for normal instance methods is a little different. It is more plausible that you want to ignore the base class implementation and provide a brand new implementation. But take the decision based on what the derived class wants to do rather than whether or not the super class has an empty implementation for the method.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • +1 for the 'implementation details' part. Indeed, some future version of the RTL might decide to actually put some important code in these empty methods. – Andreas Rejbrand Apr 19 '13 at 11:54
4

You only need to call inherited if you want the code of the ancestors to execute. Sometimtes you need that code, sometimes you do not. You can also use conditionals and call inherited only if some condition is fulfilled, and you can choose when to do it (beginning of method, end of method, ...).

Hence, it all depends on the situation.

Here's an example.

Community
  • 1
  • 1
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • I personally do it at the end, especially if i descent from TThread. –  Apr 19 '13 at 12:31
  • 5
    You do it at the end if that's the right thing to do, for example in a destructor. And at the beginning if that's the right thing to do, for example in a constructor. And likewise, you might do it in the middle of the method for certain instance methods. If you descend from `TThread`, there's no need to call the inherited constructor as the last thing that you do in your constructor. I think you are mistakenly thinking that the inherited constructor starts executing the thread. It does not. That happens in `AfterConstruction`. – David Heffernan Apr 19 '13 at 12:50
0

Even though TObject's Create/Destroy methods don't do anything in the current version, they might in some future version (unlikely, but still might). So is it a MUST for you right now? No, because it won't accomplish anything, but only because the current parent doesn't add any functionality.

If you want your descendant objects to always add functionality to their parents, it would probably be a good idea to consistently call inherited.

David Cornelius
  • 437
  • 1
  • 5
  • 12