Generics and constraints in Delphi is still a bit of pain.
A while ago, I needed a factory for threads. It was more convoluted than I meant it to be, so I had a short chat with Stefan Glienke.
He came up with an example similar to the one below. I tore it apart so you can on each line see what the compiler dislikes.
This fails, but was kind of how I wanted it to be:
type
TFactory = record
class function Manufacture<T: TBaseClass, constructor>(parameter definitions): T;
end;
class function Manufacture<T: TBaseClass, constructor>(parameter definitions): T;
begin
Result := T.Create(parameter values);
end;
Which means I need to update Delphi Constraints in Generics – RAD Studio XE documentation wiki
The factory:
type TComponentFactory = class class function CreateComponent<T: TComponent>(AOwner: TComponent): T; static; end; class function TComponentFactory.CreateComponent<T>(AOwner: TComponent): T; var ComponentClass: TComponentClass; Component: TComponent; begin ComponentClass := T; Component := ComponentClass.Create(AOwner); // you can't do `T.Create(AOwner)` Result := T(Component); // you can't do `Result := ComponentClass.Create(AOwner);` end;
The usage:
var Component: TButton; Owner: TComponent; begin Owner := Application.MainForm; Component := TComponentFactory<TButton>.CreateComponent(Owner); Component.Parent := Owner; end;
Full source example is at: After a discussion with Stefan Glienke: a pattern for a factory, this one for components, but can be uses for anything having a base class like a TThread descendant.
In the mean time, Spring4D has added the [Archive.is] Spring4D: TActivator record with many CreateInstance methods that allow you to create instances of classes for which you just have type information.
–jeroen
This fails:
type
TFactory = record
class function Manufacture<T: TBaseClass, constructor>(parameter definitions): T;
end;
class function Manufacture<T: TBaseClass, constructor>(parameter definitions): T;
begin
Result := T.Create(parameter values);
end;
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type | |
| TComponentFactory = class | |
| class function CreateComponent<T: TComponent>(AOwner: TComponent): T; static; | |
| end; | |
| class function TComponentFactory.CreateComponent<T>(AOwner: TComponent): T; | |
| var | |
| ComponentClass: TComponentClass; | |
| Component: TComponent; | |
| begin | |
| ComponentClass := T; | |
| Component := ComponentClass.Create(AOwner); // you can't do `T.Create(AOwner)` | |
| Result := T(Component); // you can't do `Result := ComponentClass.Create(AOwner);` | |
| end; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var | |
| Component: TButton; | |
| Owner: TComponent; | |
| begin | |
| Owner := Application.MainForm; | |
| Component := TComponentFactory<TButton>.CreateComponent(Owner); | |
| Component.Parent := Owner; | |
| end; |







