Howdey,德爾福 - 無法投TVirtualInterface到虛擬接口
我使用TVirtualInterface實現一些接口的基本接口。這些interfaes代表可以在數據庫中找到的Keys。我使用定製的代碼生成器生成接口定義。例如:
// Base code
IKey = interface
function KeyFields : string;
function KeyValues : Variant;
function GetKeyValue(const aKeyName : string) : Variant;
procedure SetKeyValue(const aKeyName : string; Value : Variant);
end;
// Generated code
ITable1Key = interface(IKey)
end;
ITable1Key1 = interface(ITable1Key)
procedure SetField1(const Value : string);
function GetField1 : string;
property Field1 : string read GetField1 write SetField1;
end;
ITable1Key2 = interface(ITable1Key)
procedure SetField1(const Value : string);
function GetField1 : string;
property Field1 : string read GetField1 write SetField1;
procedure SetField2(const Value : string);
function GetField2 : string;
property Field2 : string read GetField1 write SetField1;
end;
// Other generated declarations
我使用TVirtualInterface來實現每個IKey接口,而不是逐個實現它們。
雖然,在我TVirtualInterface:
TKey = TVirtualInterface
public
constructor Create(aType : PTypeInfo);
function Cast : IKey;
end;
TKey<T : IKey>
public
constructor Create; reintroduce;
function Cast : T;
end;
constructor TKey.Create(aType : PTypeInfo)
begin
inherited Create(aType, aHandlerMethod);
end;
function TKey.Cast;
var
pInfo: PTypeInfo;
begin
pInfo := TypeInfo(IKey);
if QueryInterface(GetTypeData(pInfo).Guid, Result) <> 0 then
begin
raise Exception.CreateFmt('Sorry, TKey is unable to cast %s to its interface ', [string(pInfo.Name)]);
end;
end;
constructor TKey<T>.Create;
begin
inherited Create(TypeInfo(T));
end;
function TKey<T>.Cast;
var
pInfo: PTypeInfo;
begin
pInfo := TypeInfo(T);
if QueryInterface(GetTypeData(pInfo).Guid, Result) <> 0 then
begin
raise Exception.CreateFmt('Sorry, TKey<T> is unable to cast %s to its interface ', [string(pInfo.Name)]);
end;
end;
我沒有問題,鑄造TKEY的虛擬接口使用TKey.Cast方法的T型,雖然TKey.Cast返回不支持錯誤接口。
我System.Rtti檢查,這不是工作,我想它的方式部分:
function TVirtualInterface.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if iid = FIID then
begin
_AddRef;
Pointer(Obj) := @VTable;
Result := S_OK;
end
else
Result := inherited
end;
現在,我怎麼能強迫TVirtualInterface將自己轉換爲IID作爲父FIID字段的界面?我是否必須爲IKey界面創建另一個TVirtualInterface實例?
非常感謝。
這是「限制」一個新問題嗎?在Delphi中,你總是必須聲明繼承接口的實現,其中一個類直接實現派生接口和任何基接口,但接口實現是(或曾經是)從該基類自身聲明的基類繼承接口的實現。唯一的問題是如果基類實現了接口的方法而沒有實際聲明接口本身的實現。除非我的記憶力正在玩技巧(我目前沒有德爾福交手測試)。 – Deltics
@Deltics:「*這個」限制「是一個新問題嗎?*」 - 不,它一直在那裏。接口方法的實現可以像預期的那樣通過普通多態性從基類繼承到派生類,但是必須在每個派生類聲明中指定接口以便出現在每個類的內部接口表中,所以'TObject.GetInterface() (通過擴展,'IInterface.QueryInterface()',''as''和'as'運算符,'SysUtils。Supports()'等)可以看到它。不理想,C++沒有這個限制。 –