Delphi generics TObjectList<T> inheritance
我想创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 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 |
似乎有以下声明:
1 | >>> TCatalogueItemList = class(TIndexedObjectList<TCatalogueItem>) <<<< |
导致以下编译器错误:
[DCC Error] edGenerics.pas(106): E2010 Incompatible types:
'TCatalogueItem' and 'TIndexedObject'
但是编译器在编译单元的末尾(第 106 行)显示错误,而不是在声明本身上,这对我来说没有任何意义...
基本上我的想法是我有一个从 TObjectList 下降的通用列表,我可以根据需要扩展新功能。对此的任何帮助都会很棒!!!
我应该使用 Delphi 2010 添加。
谢谢。
您的错误在于类型转换,编译器错误是可以的(但它无法在我的 Delphi XE3 中找到正确的文件)。
您的 ItemByIndex 方法已声明:
1 | TIndexedObjectList< T >.ItemByIndex(AIndex: Integer): T; |
但是你有这行:
1 | Result := TIndexedObject(nil); |
这对于父类
您可能知道,
1 2 3 | function TCatalogueItemList.ItemByIndex(AIndex: Integer): TCatalogueItem; begin Result := TIndexedObject(nil); //did you see the problem now? |
要将结果初始化为 nil 值,可以调用 Default() 伪函数,如下所示:
1 | Result := Default(T); |
在 Delphi XE 或更高版本中,该解决方案也是通用的。不是将结果类型转换为固定的
应用泛型类型转换
1 2 3 | Result := T(nil); //or Result := T(SomeOtherValue); |
但是,在这种特定情况下,不需要对
它会编译,并希望能像你期望的那样工作。