2009-02-24 49 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.