我创建了几个接口来描述集合及其项目:IetCollection和IetCollectionItem。当然,我有两个实现这两个接口的类:TetCollection和TetCollectionItem(都继承自TInterfacedObject。)
然后我有一系列接口,其中顶级接口继承自IetCollectionItem,其余接口来自它(让我们称之为ISomeBasicType和ISomeSpecificType1以及ISomeSpecificType2。)
类TSomeBasicType继承自类TetCollectionItem,并且还实现了ISomeBasicType。层次结构中的其他类继承自TSomeBasicType并实现其各自的接口(即ISomeSpecificType1和ISomeSpecificType2。)
当我填充集合时,我使用工厂方法来获取对ISomeBasicType的引用。到目前为止,一切正常。
但是当我尝试遍历集合并询问集合项是否支持ISomeSpecificType1或ISomeSpecificType2时,我得到的答案是否。
我一直在努力解决这个问题,但我没有取得任何成果,所以任何帮助都会受到高度赞赏。
以下是一些代码:
// This is the basic type
IetCollectionItem = interface
end;
// Implementation of the basic type
TetCollectionItem = class(TInterfacedObject, IetCollectionItem)
end;
ISomeBasicType = interface(IetCollectionItem)
end;
ISomeSpecificType1 = interface(ISomeBasicType)
end;
// Implements ISomeBasicType, should inherit implementation of IetCollectionItem
// from TetCollectionItem
TSomeBasicType = class(TetCollectionItem, ISomeBasicType)
end;
// Implements ISomeSpecificType1, should inherit implementation of ISomeBasicType
// from TSomeBasicType and implementation of IetCollectionItem from
// TetCollectionItem
TSomeSpecificType1 = class(TSomeBasicType, ISomeSpecificType1)
end;
这是我用户填充集合的代码:
var
aBaseType: ISomeBasicType;
aSpecificType: ISomeSpecificType1;
begin
aBaseType:= TheFactory(anID, aType); // Returns a reference to ISomeBasicType
if Supports(aBaseType, ISomeSpecificType1, aSpecificType) then
begin
// Do something to the specific type
aTypeCollection.Add(aSpecificType);
end
else
aTypeCollection.Add(aBaseType);
这是失败的代码:我遍历集合,然后检查其中的任何项是否支持其中一个子接口。
var
iCount: Integer;
aBaseType: ISomeBasicType;
aSpecificType: ISomeSpecificType1;
begin
for iCount:= 0 to Pred(aTypeCollection.Count) do
begin
aBaseType:= aTypeCollection[iCount];
// This is where Supports fails
if Supports(aBaseType, ISomeSpecificType1, aSpecificType) then
begin
end;
end;
end;
以下是TheFactory的代码:
function TheFactory(const anID: Integer; const aType: TetTypes): ISomeBasicType;
begin
Result:= nil;
case aType of
ptType1 : Result:= TSomeSpecificType1.Create(anID, aType);
ptType2 : Result:= TSomeSpecificType2.Create(anID, aType);
end;
Assert(Assigned(Result), rcUnknonwPhenomenonType);
end; {TheFactory}
答案 0 :(得分:6)
虽然你的代码让我感到头晕,但是从你的问题标题中我感觉我知道你的问题在哪里。遗憾的是,Delphi的接口多态性不像Delphi的类多态(我在某处读过这篇文章,这与以前的COM接口兼容性有关)。关键是,如果您要查询特定接口的类实例,Delphi只会找到直接在类声明中列出的接口,尽管类声明中的另一个接口可能是从您要查询的接口继承的。看到这个简单的例子来理解我的意思。 对不起,如果我的回答完全错过了你的问题。
type
TForm61 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
IBase = interface
['{AE81FB3C-9159-45B0-A863-70FD1365C113}']
end;
IChild = interface(IBase)
['{515771E7-44F6-4819-9B3A-F2A2AFF74543}']
end;
TBase = class(TInterfacedObject, IBase)
end;
TChild = class(TInterfacedObject, IChild)
end;
TChildThatSupportsIbase = class(TChild, IBase)
end;
var
Form61: TForm61;
implementation
{$R *.dfm}
procedure TForm61.Button1Click(Sender: TObject);
var
Child: IChild;
ChildThatSupportsIbase: IChild;
begin
Child := TChild.Create;
ChildThatSupportsIbase:= TChildThatSupportsIbase.Create;
if Supports(Child, IBase) then
ShowMessage('TChild supports IBase')
else
ShowMessage('TChild doesn''t supports IBase');
if Supports(ChildThatSupportsIbase, IBase) then
ShowMessage('TChildThatSupportsIbase supports IBase')
else
ShowMessage('TChildThatSupportsIbase doesn''t supports IBase');
end;
答案 1 :(得分:2)
编辑示例代码以使用您的类层次结构。两个Supports
调用都返回True。我只在你的界面添加了GUID。
如果我的水晶球处于正常工作状态,你就忘了给你的接口GUID了。
这是一个证据,证明你认为我认为的作品。如果这不是您要求的,请使用提示并使用简短但完整的控制台应用程序替换代码块,以清楚地显示问题:
program Project29;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// This is the basic type
IetCollectionItem = interface
end;
// Implementation of the basic type
TetCollectionItem = class(TInterfacedObject, IetCollectionItem)
end;
ISomeBasicType = interface(IetCollectionItem)
['{F082CD83-5030-42EE-A1A8-FF91769F986F}']
end;
ISomeSpecificType1 = interface(ISomeBasicType)
['{8789FD5A-FC94-4F19-B28B-8ABA67D66DAE}']
end;
// Implements ISomeBasicType, should inherit implementation of IetCollectionItem
// from TetCollectionItem
TSomeBasicType = class(TetCollectionItem, ISomeBasicType)
end;
// Implements ISomeSpecificType1, should inherit implementation of ISomeBasicType
// from TSomeBasicType and implementation of IetCollectionItem from
// TetCollectionItem
TSomeSpecificType1 = class(TSomeBasicType, ISomeSpecificType1)
end;
var iBase: IetCollectionItem;
begin
iBase := TSomeSpecificType1.Create;
if Supports(iBase, iSomeBasicType) then
WriteLn('iBase supports iSomeBasicType')
else
WriteLn('iBase does not support iSomeBasicType');
if Supports(iBase, ISomeSpecificType1) then
WriteLn('iBase supports ISomeSpecificType1')
else
WriteLn('iBase does not support ISomeSpecificType1');
WriteLn('Press ENTER'); Readln;
end.
答案 2 :(得分:0)
首先,在列表中放置一些明显不支持ISomeSpecificType1的内容:
if Supports(aBaseType, ISomeSpecificType1, aSpecificType) then
begin
// Do something to the specific type
aTypeCollection.Add(aSpecificType);
end
else
aTypeCollection.Add(aBaseType); //<------- this
然后你想知道为什么它不支持ISomeSpecificType1。
究竟是什么问题?为什么你认为集合中的所有项目甚至任何项目都应该支持ISomeSpecificType1?
可能是您添加的每个项目都不支持它。