Delphi Generics: constructor restriction

As promised in the previous post “Delphi: Default parameterless constructor” I will now try to create a new generic class that accepts a type parameter that has a “constructor” restriction (must have a default public parameterless constructor).

Let’s start off with a simple example:

type
  TMyClass = class
  end;

  TMyGenericClass<T: constructor> = class
  end;

var
  GenObj: TMyGenericClass<TMyClass>;

begin
end.

This is a legitimate example that will compile. TMyClass inherits the default parameterless constructor from TObject. Even though this is not the result that you would expect in other languages, it’s still somehow correct.

Moving further, let’s check what happens if we declare a private default constructor:

type
  TMyClass = class
  private
    constructor Create();
  end;

  TMyGenericClass<T: constructor> = class
  end;

{ TMyClass }
constructor TMyClass.Create();
begin
  WriteLn('TMyClass.Create()');
end;

var
  GenObj: TMyGenericClass<TMyClass>;

begin
end.

And here we will get a compile error. The requirement that TMyClass has a public parameterless constructor is not satisfied!

But don’t be too happy just yet! The next example cracks it again:

type
  TMyClass = class
  public
    constructor Create(const AParam: String);
  end;

  TMyGenericClass<T: constructor> = class
  end;

{ TMyClass }
constructor TMyClass.Create(const AParam: String);
begin
  WriteLn('TMyClass.Create()');
end;

var
  GenObj: TMyGenericClass<TMyClass>;

begin
end.

It seems that the default constructor is yet again found — the one inherited from TObject.

The last one (I promise!) follows:

type
  TMyClass = class
  private
    constructor Create(); overload;
  public
    constructor Create(const AParam: String); overload;
  end;

  TMyGenericClass<T: constructor> = class
  end;

{ TMyClass }
constructor TMyClass.Create(const AParam: String);
begin
  WriteLn('TMyClass.Create()');
end;

constructor TMyClass.Create;
begin
end;

var
  GenObj: TMyGenericClass<TMyClass>;

begin
end.

Again, a compilation error is risen. We’re back on the right track.

The final conclusion to this post and the previous one is:

If you do not have/need a default public parameterless constructor in your class, you must still define a private one that would raise an Exception telling the programmer to not call it. Doing this you will ensure that your constructor is being executed and not the TObject provided one, resulting in a predictable object state. Also this will ensure that the “constructor” restriction will be enforced correctly!

~Yes, I know, Delphi sucks sometimes 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.