我创建了几个接口来描述集合及其项目: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;
Run Code Online (Sandbox Code Playgroud)
这是我用户填充集合的代码:
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);
Run Code Online (Sandbox Code Playgroud)
这里的代码失败了:我遍历集合,然后检查其中的任何项是否支持其中一个子接口.
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;
Run Code Online (Sandbox Code Playgroud)
这是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}
Run Code Online (Sandbox Code Playgroud)
虽然你的代码让我很头晕,但从你的问题标题我感觉我知道你的问题在哪里.遗憾的是,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;
Run Code Online (Sandbox Code Playgroud)