Delphi通用模板类用法编译错误
我是Delphi泛型类的新手。我不知道如何在实现代码中使用泛型类。 代码如下:Delphi通用模板类用法编译错误,delphi,generics,compiler-errors,Delphi,Generics,Compiler Errors,我是Delphi泛型类的新手。我不知道如何在实现代码中使用泛型类。 代码如下: 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 TDataA
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;
.....
类型TDataElement=class(TObject)
受保护的
过程集合名(sNewValue:String);事实上的
私有的
m_sName:字符串;
出版
属性sName:String read m_sName write SetName;
结束;
类型TDataArray=class(TObject)
公众的
函数Find(dtElement:T):整数;
程序添加(DTT元素:T);
私有的
m_vContainer:T的数组;
受保护的
函数GetData(索引:整数):T;事实上的
过程SetData(索引:整数;新值:T);事实上的
公众的
属性vData[索引:整数]:T读取GetData写入SetData;
结束;
实施
函数TDataArray.Find(dtElement:T):整数;
varⅠ:整数;
开始
结果:=-1;
对于i:=0到高(m_vContainer)do
如果(m_vContainer[i]NIL)和(m_vContainer[i]=dtElement),那么
开始
结果:=i;
出口
结束;
结束;
.....
当我尝试创建泛型类的实例时,如以下代码所示:
方法1)
varz:TDataArray;
z:=TDataArray.Create();
我得到以下错误:
E2010不兼容类型:“TDataElement”和“TDataElement类”
如果我使用第二种方法,我会得到另一个奇怪的错误:
方法2)
类型TDataElementClass=TDataElement的类
var z:TDataArray<TDataElementClass>;
varz:TDataArray;
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.
System.SysUtils、类、,
“D:\VisionBot\Software\VisionBot\GUI\Units\dtArray\u unit.pas”中的dtArray\u单元;
类型TDataElement=class(TObject)
受保护的
过程集合名(sNewValue:String);事实上的
私有的
m_sName:字符串;
出版
属性sName:String read m_sName write SetName;
结束;
类型TDataArray=class(TObject)
公众的
函数Find(dtElement:T):整数;超载;
程序添加(DTT元素:T);
私有的
m_vContainer:T的数组;
受保护的
函数GetData(索引:整数):T;事实上的
过程SetData(索引:整数;新值:T);事实上的
公众的
属性vData[索引:整数]:T读取GetData写入SetData;
结束;
类型
TDerivedDataElement=类(TDataElement)
结束;
变量
z2:TDataArray;
//------------------------------------------------------------------------------
过程TDataElement.SetName(sNewValue:String);
开始
self.m_sName:=sNewValue;
结束;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
函数TDataArray.Find(dtElement:T):整数;
varⅠ:整数;
开始
结果:=-1;
对于i:=0到高(m_vContainer)do
如果(m_vContainer[i]NIL)和(m_vContainer[i]=dtElement),那么
开始
结果:=i;
出口
结束;
结束;
//------------------------------------------------------------------------------
函数TDataArray.GetData(索引:整数):T;
开始
结果:=无;
如果索引<0,则退出else
如果索引>高(索引),则退出else
结果:=self.m_vContainer[索引];
结束;
//------------------------------------------------------------------------------
过程TDataArray.Add(dtElement:T);
开始
设置长度(self.m_vContainer,长度(m_vContainer)+1);
m_vContainer[高(m_vContainer)]:=T;
结束;
//------------------------------------------------------------------------------
过程TDataArray.SetData(索引:整数;新值:T);
开始
如果索引<0,则退出else
如果索引>高(索引),则退出else
self.m_vContainer[Index]:=T;
结束;
//------------------------------------------------------------------------------
开始
尝试
z2:=TDataArray.Create();
readln;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
结束。
或者这个:
type
TDerivedDataElement = class(TDataElement)
end;
var
z: TDataArray<TDerivedDataElement>;
现在,TDataElementClass
是一个
类型的变量可以保存TDataElement
类型的实例,或者从TDataElement
派生的任何类的实例TDataElement
类型的变量可以保存类型,该类型必须是TDataElement类
,或从TDataElement
派生的任何类TDataElement
TDataArray
会导致编译器错误,但事实并非如此。考虑这个编译程序:
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.
这会失败,因为T
是一种类型而不是实例。我想你的意思是:
m_vContainer[High(m_vContainer)]:=dtElement;
或者这个:
type
TDerivedDataElement = class(TDataElement)
end;
var
z: TDataArray<TDerivedDataElement>;
现在,TDataElementClass
是一个
类型的变量可以保存TDataElement
类型的实例,或者从TDataElement
派生的任何类的实例TDataElement
类型的变量可以保存类型,该类型必须是TDataElement类
,或从TDataElement
派生的任何类TDataElement
TDataArray
会导致编译器错误,但事实并非如此。考虑这个编译程序:
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.
这会失败,因为T
是一种类型而不是实例。我想你的意思是:
m_vContainer[High(m_vContainer)]:=dtElement;
看起来你把元类和类混在一起了。如何声明z
T:TDataElement
意味着可以用TDataElement
类或任何后代类替换T
,但不能用TDataElement
元类(TDataElement的class
)替换。我完全不知道元类和类之间的区别。我做了一个小编辑。即使我这样做:var z:TDataArray;z:=TDataArray.Create();我仍然得到错误(第一个方法)注意,内部错误始终是编译器中的错误。那意味着你不是在做什么
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;
m_vContainer[High(m_vContainer)]:=dtElement;