我在以下代码中获得E2010 Incompatible types: 'TDerivedFrame' and 'TBaseFrame'
:
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>;
仅使用T.Create(nil)
会导致E2568 Can't create new instance without CONSTRUCTOR constraint in type parameter declaration
。
据我所知,你只能使用无参数构造函数创建一个构造函数约束。
这样做的正确方法是什么?
PS:代码在我删除变量时编译,这让我觉得这是编译器错误?!
编辑:我理解E2010错误,但即使使用T(TBaseFrame(T).Create(nil))
它也无效。这会编译,但会在运行时导致访问冲突:
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.
答案 0 :(得分:4)
FFrame := T(TBaseFrameClass(T).Create(nil));
是执行此操作的正确方法。
你需要
type
TBaseFrameClass = class of TBaseFrame;
您的编译器错误是因为您实例化类型TContainer<TDerivedFrame>
。当您实例化该类型时,您要求编译器处理
FFrame := TBaseFrame(...);
其中FFrame
为TDerivedFrame
。如果您在没有泛型的情况下编写该代码,您就会理解编译器错误。
所以,编译器在这里表现正常,但是实例化的问题正在抓住你。只有在实例化时,编译器错误才会变得明显。没有实例化,如果你实例化了TContainer<TBaseFrame>
,那么就没有编译器错误。
AV是因为您将T
转换为实例而不是类。
答案 1 :(得分:0)
尝试使用这个:
TContainer<T:constructor, TBaseFrame> = class