2009-02-24 82 views
2

我想创建一个通用列表类与tiOPF(delphi @ www.tiopf.com的对象持久化框架)一起使用。具体来说,我正在尝试使用现有的泛型类(TtiObjectList)并制作一个使用TtiObject降级的泛型版本。德尔菲通用约束问题

由于需要在D7 - D2009和Free Pascal下编译,所以我修改基类的范围有限。我需要从TtiObjectList下降以保持现有的持久性机制正常工作。

// base class 
type 
    TtiObjectList = class(TtiObject) 
... 
protected 
    function GetItems(i: integer): TtiObject; virtual; 
    procedure SetItems(i: integer; const AValue: TtiObject); virtual; 
... 
public 
    function Add(const AObject : TtiObject): integer; overload; virtual; 
... 
end; 

我的类定义如下:

TtiGenericObjectList<T: TtiObject> = class(TtiObjectList) 
protected 
    function GetItems(i:integer): T; reintroduce; 
    procedure SetItems(i:integer; const Value: T); reintroduce; 
public 
    function Add(const AObject: T): integer; reintroduce; 
    property Items[i:integer]: T read GetItems write SetItems; default; 
end; 

implementation 

{ TtiGenericObjectList<T> } 

function TtiGenericObjectList<T>.Add(const AObject: T): integer; 
var obj: TtiObject; 
begin 
    obj:= TtiObject(AObject); /// Invalid typecast 
    result:= inherited Add(obj); 
end; 

// alternate add, also fails 
function TtiGenericObjectList<T>.Add(const AObject: T): integer; 
begin 
    result:= inherited Add(AObject); /// **There is no overloaded version** 
/// **of 'Add' that can be called with these arguments** 
end; 

function TtiGenericObjectList<T>.GetItems(i: integer): T; 
begin 
    result:= T(inherited GetItems(i)); /// **Invalid typecast ** 
end; 

procedure TtiGenericObjectList<T>.SetItems(i: integer; const Value: T); 
begin 
    inherited SetItems(i, Value); 
end; 

我的问题是,德尔福没有看到T作为一个TtiObject后代。我收到无效的类型转换错误,当我做这样的事情:

function TtiGenericObjectList<T>.Add(const AObject: T): integer; 
var obj: TtiObject; 
begin 
    obj:= TtiObject(AObject); /// **Invalid typecast*** 
    result:= inherited Add(obj); 
end; 

如果我不这样做类型转换,然后我得到过载的错误,而不是在上面的列表中显示。

任何想法我错了吗?

肖恩

+0

这是Delphi 2009编译器中的一个错误;我认为这是在Delphi 2010编译器中解决的。 – 2009-10-27 11:05:14

回答

2

它看起来像问题不是我,但编译器:)。

最后,我周围有使用以下方法

class function TtiGenericObjectList<T>.GenericAsObject(const Value): TObject; 
begin 
    Result := TObject(Value); 
end; 

class function TtiGenericObjectList<T>.ObjectAsGeneric(const Value): T; 
begin 
    Result := T(Value); 
end; 

使用如下

function TtiGenericObjectList<T>.Add(const AObject: T): integer; 
var obj: TtiObject; 
begin 
    obj:= TtiObject(GenericAsObject(AObject)); 
    result:= inherited Add(obj); 
    // replaces the following which gets overload errors 
// result:= inherited Add(TtiObject(AObject)); 
end; 

function TtiGenericObjectList<T>.GetItems(i: integer): T; 
var obj: TtiObject; 
begin 
    obj:= inherited GetItems(i); 
    result:= ObjectAsGeneric(obj); 
    // replaces the following which gets "Invalid typecast" errors 
    // result:= inherited Add(AObject); 
end; 

我会清理这些了一下,砍死使用它们直到编译器得到修复。

0

我已经发现了一些小问题与仿制药,这并不奇怪,这样一个新功能。并且你试图很难将编译器弄糊涂;-)。

不幸的是我没有在2009年这里的手,所以我无法测试,但我有一些建议:

你有没有更新(并安装它们)?

您是否尝试过使用的是运营商:

obj:= AObject as TtiObject; 

您是否尝试过使用中间类:

TtiGenericList<T: TObject> = class(TtiObjectList) 
protected 
    function GetItems(i:integer): T; reintroduce; 
    procedure SetItems(i:integer; const Value: T); reintroduce; 
public 
    function Add(const AObject: T): integer; reintroduce; 
    property Items[i:integer]: T read GetItems write SetItems; default; 
end; 
+0

我已经尝试过所有这些东西:( – SeanX 2009-02-24 19:33:30

2

德尔福2009年编译器在其仿制药实行一些非常严重的缺陷。它并不理解约束条件的影响(Barry Kelly在其他地方承认这一点;我不记得具体位置在哪里),而且跨单元的泛型会导致非常奇怪的问题。最好的办法是根据具体情况处理这个问题:如果你的代码编译,使用它。如果不是,则返回到非通用实现,直到它们得到修复。希望在不久的将来我们会看到一个更新修正了泛型(和Generics.Collections单元)。

1

我最近用D2010解决了一个类似的问题,下面是我提出的代码。

type 
    TGenericList<T: TtiObject> = class(TtiObjectList) 
    protected 
    function GetItems(AIndex: integer): T; reintroduce; 
    procedure SetItems(AIndex: integer; const AValue: T); reintroduce; 
    public 
    property Items[i:integer]: T read GetItems write SetItems; default; 
    function Add(const AObject: T): integer; reintroduce; 
    end; 

implementation 

{ TGenericList<T> } 

function TGenericList<T>.Add(const AObject: T): integer; 
begin 
    Result := inherited Add(TtiObject(AObject)); 
end; 

function TGenericList<T>.GetItems(AIndex: integer): T; 
begin 
    Result := T(inherited GetItems(AIndex)); 
end; 

procedure TGenericList<T>.SetItems(AIndex: integer; const AValue: T); 
begin 
    inherited SetItems(AIndex, AValue); 
end; 
0

(我来到这里,由于类似的问题,但同时钉下来我有一个新的(XE)德尔福得到了不同的解决方案,虽然):

或者干脆尽量让本地变量Obj类型T.