If you want to work with a generic type, you need to store the type of generic you're working with somewhere.
There is no type that can hold a type parameter
however. You'll either have to store the type of T
in the class itself, or figure out some other way of doing things.
You have two options:
Recommended option
Redeclare NavControl
like so:
type
TNavControl<T:class, constructor> = class
private
_Plist: TObjectList<T>;
public
constructor Create(const List: TObjectList<T>);
Creating new instances of T
in your NavControl
is easy:
begin
NewItem:= T.Create;
.....
Mishmash of generic and old-skool -not recommended-
The other way is to recognise that T
is an object, as such you can store its class in a variable of type TClass, however in order to do so you'll have to get a little creative in your constructor.
type
TNavControl = class
private
_PList: TObjectList<TObject>;
ClassOfT: TClass;
constructor TNavControl.Create<T:class, constructor>(const List: TObjectList<T>);
var
Dummy: T;
begin
Dummy:= T.Create;
try
ClassOfT:= TObject(Dummy).ClassType;
finally
Dummy.Free;
end;
end;
You'll now have to work with the TClass
reference in order to do instantiate objects, but TClass
requires virtual constructors which the generic constraint does not -Oops-.
My recommendation
Personally I would not bother with generics here.
You know you want a class and you know you need a constructor.
Using this method allows you to use a constructor with or without parameters, as long as the constructor is virtual.
Just limit your object list to a reasonable subclass that you control and use that.
type
TMyClass = class(TControl)
...
constructor Create(const param: string = ''); virtual; <<!!!!
end;
TMyClass2 = class(TMyClass)
constructor Create(const param: string = ''); override <<!!
end;
TMyClassClass = class of TMyClass;
TNavControl = class
private
FMyClassClass = TMyClassClass;
FPList = TObjectList; //non-generic version
public
constructor Create(const ClassType: TMyClassClass);
function TNavControl.NewItem(const param: string = ''): TMyClass;
begin
Result:= FMyClassClass.Create(param); //Will create a TMyClass2 or 3
//Or whatever type you fed into the constructor.
end;
Now if you call
var
A: TMyClass2;
B: TMyClass;
C: TNavControl;
A:= TMyClass.Create('test');
C:= TNavControl.Create(A.ClassType);
B:= C.NewItem('test2'); //Creates a TMyClass2
Generics really don't have much use when working with classes, better to use the class of ...
and virtual constructors.
This also allows the use of constructors with parameters, which generic solutions do not cater for.
Just make sure to keep the constructor parameters the same throughout.
See this answer for more info: https://stackoverflow.com/a/758715/650492