加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi泛型TObjectList继承

发布时间:2020-12-15 09:36:40 所属栏目:大数据 来源:网络整理
导读:我想创建一个TObjectList T后代来处理我的应用程序中的对象列表之间的常见功能.然后我想进一步从新类继续下载,以便在需要时引入其他功能.我似乎无法使用超过1级的继承.我可能需要更多地了解泛型,但是我搜索高低都是正确的方法来做到这一点而没有成功.到目前
我想创建一个TObjectList< T>后代来处理我的应用程序中的对象列表之间的常见功能.然后我想进一步从新类继续下载,以便在需要时引入其他功能.我似乎无法使用超过1级的继承.我可能需要更多地了解泛型,但是我搜索高低都是正确的方法来做到这一点而没有成功.到目前为止,这是我的代码:

unit edGenerics;

interface

uses
  Generics.Collections;

type

  TObjectBase = class
  public
    procedure SomeBaseFunction;
  end;

  TObjectBaseList<T: TObjectBase> = class(TObjectList<T>)
  public
    procedure SomeOtherBaseFunction;
  end;

  TIndexedObject = class(TObjectBase)
  protected
    FIndex: Integer;
  public
    property Index: Integer read FIndex write FIndex;
  end;

  TIndexedObjectList<T: TIndexedObject> = class(TObjectBaseList<T>)
  private
    function GetNextAutoIndex: Integer;
  public
    function Add(AObject: T): Integer;
    function ItemByIndex(AIndex: Integer): T;
    procedure Insert(AIndex: Integer; AObject: T);
  end;

  TCatalogueItem = class(TIndexedObject)
  private
    FID: integer;
  public
    property ID: integer read FId write FId;
  end;

  TCatalogueItemList = class(TIndexedObjectList<TCatalogueItem>)
  public
    function GetRowById(AId: Integer): Integer;
  end;

implementation

uses
  Math;

{ TObjectBase }

procedure TObjectBase.SomeBaseFunction;
begin
end;

{ TObjectBaseList<T> }

procedure TObjectBaseList<T>.SomeOtherBaseFunction;
begin
end;

{ TIndexedObjectList }

function TIndexedObjectList<T>.Add(AObject: T): Integer;
begin
  AObject.Index := GetNextAutoIndex;
  Result := inherited Add(AObject);
end;

procedure TIndexedObjectList<T>.Insert(AIndex: Integer; AObject: T);
begin
  AObject.Index := GetNextAutoIndex;
  inherited Insert(AIndex,AObject);
end;

function TIndexedObjectList<T>.ItemByIndex(AIndex: Integer): T;
var
  I: Integer;
begin
  Result := Default(T);
  while (Count > 0) and (I < Count) and (Result = Default(T)) do
    if Items[I].Index = AIndex then
      Result := Items[I]
    else
      Inc(I);
end;

function TIndexedObjectList<T>.GetNextAutoIndex: Integer;
var
  I: Integer;
begin
  Result := 0;
  for I := 0 to Count - 1 do
    Result := Max(Result,Items[I].Index);
  Inc(Result);
end;

{ TCatalogueItemList }

function TCatalogueItemList.GetRowById(AId: Integer): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to Pred(Self.Count) do
    if Self.Items[I].Id = AId then
    begin
      Result := I;
      Break;
    end;
end;

end.
/////// ERROR HAPPENS HERE ////// ???? why is beyond me

看来,以下声明:

>>> TCatalogueItemList = class(TIndexedObjectList<TCatalogueItem>) <<<<

导致以下编译器错误:

[DCC Error] edGenerics.pas(106): E2010 Incompatible types:
‘TCatalogueItem’ and ‘TIndexedObject’

然而,编译器在编译单元的END处显示错误(第106行),而不是在声明本身上显示错误,这对我没有任何意义……

基本上我的想法是我有一个从TObjectList开始的通用列表,我可以根据需要扩展新功能.对此有任何帮助将是伟大的!

我应该使用Delphi 2010添加.

谢谢.

解决方法

您的错误是在类型转换中,编译器错误是正常的(但它无法在我的Delphi XE3中找到正确的文件).

您的ItemByIndex方法被声明:

TIndexedObjectList<T>.ItemByIndex(AIndex: Integer): T;

但是你有这条线:

Result := TIndexedObject(nil);

这对于父类TIndexedObjectList来说很好,其中函数的结果是TIndexedObject类型,但对于后代类TCatalogueItemList则不行,其中函数的结果是TCatalogueItem类型.

您可能知道,TCatalogueItem实例与TIndexedObject变量兼容,但反之则不然.它翻译成这样的东西:

function TCatalogueItemList.ItemByIndex(AIndex: Integer): TCatalogueItem;
begin
  Result := TIndexedObject(nil);  //did you see the problem now?

要将结果初始化为nil值,可以调用Default()伪函数,如下所示:

Result := Default(T);

在Delphi XE或更高版本中,该解决方案也是通用的.您可以使用T类型应用泛型类型转换,而不是将结果类型转换为固定的TIndexedObjectList类

Result := T(nil);
//or 
Result := T(SomeOtherValue);

但是,在这种特定情况下,不需要类型转换nil常量,因为nil是一个特殊值,它与任何引用赋值兼容,所以你只需要用以下代码替换:

Result := nil;

它会编译,并希望按预期工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读