我是Delphi Generic Classes的新手。我不知道如何在实现代码中使用泛型类。 这是代码:
Type TDataElement = class(TObject)
protected
Procedure SetName(sNewValue:String); virtual;
private
m_sName:String;
published
property sName:String read m_sName write SetName;
end;
Type TDataArray<T : TDataElement> = class(TObject)
public
function Find(dtElement:T):integer;
Procedure Add(dtElement:T);
private
m_vContainer : array of T;
protected
Function GetData(Index:integer):T; virtual;
Procedure SetData(Index:integer; NewValue:T); virtual;
public
property vData[Index: Integer]: T read GetData write SetData;
end;
implementation
function TDataArray<T>.Find(dtElement:T):integer;
var i:integer;
begin
Result:=-1;
for i := 0 to high(m_vContainer) do
if (m_vContainer[i] <> NIL)and(m_vContainer[i] = dtElement) then
begin
Result:=i;
exit;
end;
end;
.....
当我尝试创建Generic Classes的实例时,如下面的代码: 的方法1)
var z:TDataArray<TDataElement>;
z:=TDataArray<TDataElement>.Create();
我收到以下错误:
E2010不兼容的类型:&#39; TDataElement&#39;和&#39;类TDataElement&#39;
如果我做第二种方法,我会得到另一个奇怪的错误: 方法2) 类型TDataElementClass = TDataElement的类;
var z:TDataArray<TDataElementClass>;
F2084内部错误:I8230
我做错了什么?
一个文件中的整个源代码
System.SysUtils,Classes,
dtArray_unit in 'D:\VisionBot\Software\VisionBot\GUI\Units\dtArray_unit.pas';
Type TDataElement = class(TObject)
protected
Procedure SetName(sNewValue:String); virtual;
private
m_sName:String;
published
property sName:String read m_sName write SetName;
end;
Type TDataArray<T : TDataElement> = class(TObject)
public
function Find(dtElement:T):integer; overload;
Procedure Add(dtElement:T);
private
m_vContainer : array of T;
protected
Function GetData(Index:integer):T; virtual;
Procedure SetData(Index:integer; NewValue:T); virtual;
public
property vData[Index: Integer]: T read GetData write SetData;
end;
type
TDerivedDataElement = class(TDataElement)
end;
var
z2: TDataArray<TDerivedDataElement>;
//------------------------------------------------------------------------------
Procedure TDataElement.SetName(sNewValue:String);
begin
self.m_sName:=sNewValue;
end;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function TDataArray<T>.Find(dtElement:T):integer;
var i:integer;
begin
Result:=-1;
for i := 0 to high(m_vContainer) do
if (m_vContainer[i] <> NIL)and(m_vContainer[i] = dtElement) then
begin
Result:=i;
exit;
end;
end;
//------------------------------------------------------------------------------
Function TDataArray<T>.GetData(Index:integer):T;
begin
Result:=NIL;
if Index < 0 then exit else
if Index > high(Index) then exit else
Result:=self.m_vContainer[Index];
end;
//------------------------------------------------------------------------------
Procedure TDataArray<T>.Add(dtElement:T);
begin
SetLength(self.m_vContainer,Length(m_vContainer)+1);
m_vContainer[High(m_vContainer)]:=T;
end;
//------------------------------------------------------------------------------
Procedure TDataArray<T>.SetData(Index:integer; NewValue:T);
begin
if Index < 0 then exit else
if Index > high(Index) then exit else
self.m_vContainer[Index]:=T;
end;
//------------------------------------------------------------------------------
begin
try
z2:= TDataArray<TDerivedDataElement>.Create();
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
答案 0 :(得分:4)
var
z: TDataArray<TDataElementClass>;
问题是TDataElementClass
不是从TDataElement
派生的类。
以下内容有效:
var
z: TDataArray<TDataElement>;
或者这个:
type
TDerivedDataElement = class(TDataElement)
end;
var
z: TDataArray<TDerivedDataElement>;
在您的代码中
type
TDataElementClass = class of TDataElement;
现在,TDataElementClass
是metaclass。
TDataElement
类型的变量可以包含TDataElement
类型的实例,或者来自TDataElement
的任何类的实例。TDataElementClass
类型的变量可以包含类型,必须为TDataElement
,或者来自TDataElement
的任何类。您在问题中声称使用TDataArray<TDataElement>
会导致编译器错误,但事实并非如此。考虑一下这个编译程序:
type
TDataElement = class
end;
type
TDataArray<T: TDataElement> = class
public
function Find(dtElement: T): Integer;
private
m_vContainer: array of T;
end;
function TDataArray<T>.Find(dtElement: T): Integer;
begin
for Result := 0 to high(m_vContainer) do
if (m_vContainer[Result] <> nil) and (m_vContainer[Result] = dtElement) then
exit;
Result := -1;
end;
var
arr: TDataArray<TDataElement>;
begin
arr := TDataArray<TDataElement>.Create;
end.
在编辑中显示以下代码:
Procedure TDataArray<T>.Add(dtElement:T);
begin
SetLength(self.m_vContainer,Length(m_vContainer)+1);
m_vContainer[High(m_vContainer)]:=T;
end;
错误的一行在这里:
m_vContainer[High(m_vContainer)]:=T;
这会失败,因为T
是一个类型而不是一个实例。我想你的意思是:
m_vContainer[High(m_vContainer)]:=dtElement;