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;
|
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; |
|
var |
|
Component: TButton; |
|
Owner: TComponent; |
|
begin |
|
Owner := Application.MainForm; |
|
Component := TComponentFactory<TButton>.CreateComponent(Owner); |
|
Component.Parent := Owner; |
|
end; |
Like this:
Like Loading...