Reputation: 14873
I get E2010 Incompatible types: 'TDerivedFrame' and 'TBaseFrame'
on the following code:
type
TBaseFrame = class(TFrame)
end;
TDerivedFrame = class(TBaseFrame)
end;
TContainer<T: TBaseFrame> = class
private
FFrame: T;
public
property Frame: T read FFrame;
constructor Create;
end;
constructor TContainer<T>.Create;
begin
inherited;
FFrame := TBaseFrame(T).Create(nil);
end;
var
FTab: TContainer<TDerivedFrame>;
Using only T.Create(nil)
causes E2568 Can't create new instance without CONSTRUCTOR constraint in type parameter declaration
.
As far as I know you can only create a constructor constraint with a parameterless constructor.
What is the correct way to do this?
PS: The code compiles when I remove the variable which makes me think this is a compiler error?!
Edit: I understand the E2010 error, but even with T(TBaseFrame(T).Create(nil))
it doesn't work. This compiles, but causes an access violation at runtime:
type
TBaseFrame = class(TFrame)
public
constructor Create(AOwner: TComponent); override;
end;
TDerivedFrame = class(TBaseFrame)
public
constructor Create(AOwner: TComponent); override;
end;
TContainer<T: TBaseFrame> = class
private
FFrame: T;
public
property Frame: T read FFrame;
constructor Create;
end;
constructor TBaseFrame.Create(AOwner: TComponent);
begin
inherited;
end;
constructor TDerivedFrame.Create(AOwner: TComponent);
begin
inherited;
end;
constructor TContainer<T>.Create;
begin
inherited;
FFrame := T(TBaseFrame(T).Create(nil));
end;
var
FTab: TContainer<TDerivedFrame>;
begin
FTab := TContainer<TDerivedFrame>.Create;
end.
Upvotes: 3
Views: 1961
Reputation: 1
Try to use this one:
TContainer<T:constructor, TBaseFrame> = class
Upvotes: 0
Reputation: 612993
FFrame := T(TBaseFrameClass(T).Create(nil));
is the correct way to do this.
You'll need
type
TBaseFrameClass = class of TBaseFrame;
Your compiler error is because you are instantiating a type, TContainer<TDerivedFrame>
. When you instantiate that type you ask the compiler to deal with
FFrame := TBaseFrame(...);
where FFrame
is TDerivedFrame
. If you wrote that code out without generics you'd understand the compiler error.
So, the compiler is behaving correctly here, but the issue of instantiation is catching you out. It's only at the point of instantiation that the compiler error becomes apparent. Without instantiation, of if you had instantiated TContainer<TBaseFrame>
there would be no compiler error.
The AV is because you were casting T
to be an instance rather than a class.
Upvotes: 5