Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use case for the constructor constraint in Delphi?

The title is pretty much it...

Why would you ever want to use the constructor constraint?

It's clearly implied by the class constraint.

If you use it alone, you can't do anything with the thing you've created.

Why does it even exist?

Additional info:

Just as a note, the following code doesn't compile until you add the "constructor" constraint:

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;


type
  TSomeClass<T: class> = class
    function GetType: T;
  end;


{ TSomeClass<T> }

function TSomeClass<T>.GetType: T;
begin
  Result := T.Create;
end;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
like image 576
Nick Hodges Avatar asked Dec 26 '22 14:12

Nick Hodges


2 Answers

Why would you ever want to use the constructor constraint?

It's clearly implied by the class constraint.

No it's not. The constructor constraint requires that the type has a public, parameterless constructor - and then allows that constructor to be called.

Not all classes have a public parameterless constructor.

like image 62
Jon Skeet Avatar answered Dec 29 '22 04:12

Jon Skeet


IMHO the official reason for that constraint is that the compiler can't handle it actually by himself.

It is just a flag for the compiler which can also be set by himself, because the compiler does recognizes the fact, that we need a constructor constraint. So it could be handled automatically by the compiler, because the Generic class will be compiled before using that class.

Maybe we will get it with XE9

UPDATE

If TComponent is accepted as a class type without a public parameterless constructor then the constructor constraint is useless, because this (extended sample from Nick) compiles and produces a TComponent Instance. Of course it will not call the original constructor TComponent.Create( AOwner : TComponent ), instead TObject.Create is called, but you have a TComponent Instance.

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes;

type
  TSomeClass<T: class, constructor> = class
    function GetType: T;
  end;

{ TSomeClass<T> }

function TSomeClass<T>.GetType: T;
begin
  Result := T.Create;
end;

var
  SomeClass : TSomeClass<TComponent>;
  Component : TComponent;
begin
  try
    SomeClass := TSomeClass<TComponent>.Create;
    Component := SomeClass.GetType;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

UPDATE

TSomeClass<T: class, constructor>

has the same meaning as

TSomeClass<T: constructor>

because a record can have a constructor, but not a parameterless, so we have an implicit constraint to a class. And turning this around

TSomeClass<T: class>

could have an implicit constructor constraint

like image 28
Sir Rufo Avatar answered Dec 29 '22 04:12

Sir Rufo