24

Rant: Should I call "inherited" in the constructor of a class derived from TObject or TPersistent?

constructor TMyObject.Create; begin inherited Create; // Delphi doc: Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that need to be saved to a stream or have their properties assigned to other objects. VectorNames := TStringList.Create; Clear; end; 

4 Answers 4

40

Yes. It does nothing, true, but it's harmless. I think there is value in being consistent about always calling the inherited constructor, without checking to see if there is, in fact, an implementation. Some will say that it's worth calling inherited Create because Embarcadero might add an implementation for TObject.Create in the future, but I doubt this is true; it would break existing code which does not call inherited Create. Still, I think it is a good idea to call it for the reason of consistency alone.

Sign up to request clarification or add additional context in comments.

7 Comments

IIRC, the basic storage is already allocated before your constructor (Create) is called.
mj2008, you are right. Stijn, you are wrong. Read the source!
I think the most important reason is the one Gamecat stated - at some point you may want to reparent your class from TObject to something else and new class may contain non-trivial constructor.
@Stijn, the constructor of TObject does nothing, allocating storage is done by NewInstance, initalizing by InitInstance. Both class methods of TObject.
But don't call inherited on methods that override abstract methods (or have stuff like Assert('Create must be overridden') in the base class!
|
13

I always do this.

If you are refactoring and move code to a common ancestor, calling the inherited Create has the following advantages:

  1. If the common ancestor has a constructor, you can't forget to call it.
  2. If the common ancestor has a constructor with different parameters, the compiler warns you for this.

1 Comment

Although Craig is right offcourse, these are also my main reasons to call inherited Create, more so than being consistent.
3

You can also override "procedure AfterConstruction". This procedure is always called, no matter what kind of constructor.

public procedure AfterConstruction; override; end; procedure TfrmListBase.AfterConstruction; begin inherited; //your stuff, always initialized, no matter what kind of constructor! end; 

For example: if you want to create an object with a different constructor than the normal TObject.Create, such as TComponent.Create(AOwner) or a custom (overloaded) constructor, you can get problems because your override is not called and (in this case) your "VectorNames" variable will be nil.

2 Comments

If your overridden constructor isn't called, then it's a bug in your descendant class. That's a problem for the descendant-class developer to worry about, not you. And it IS possible to skip a call to AfterConstruction, for the same reason you can skip a call to the constructor: The descendant provides its own implementation and neglects to call the inherited method.
Rob: If you make a factory class, which generates TObject descendants, you cannot use TObject.Create() because it is not virtual! And if you make a TComponent descendant in your factory: it has a different constructor (Create(AOwner)). That's why you should use AfterConstruction: it is always called, no matter what kind of constructor
2

I call it, except when i need a very optimized constructor.

2 Comments

You need to post this as a comment, not as an answer. The answers must be complete AND well documented. Yours is none of this.
What? Optimized constructors don't need to call "inherited" ? How is your code working without inherited?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.