Base Delphi接口不能以多态方式工作

Ang*_*zis 3 delphi delphi-7

我创建了几个接口来描述集合及其项目: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)

iam*_*osy 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;
Run Code Online (Sandbox Code Playgroud)

  • COM的东西来自COM如何查询类工厂IIRC的错误,它会在它要求后代之前要求祖先,如果它有了祖先,它会很乐意使用它而不是获得更多的派生接口.因此,对于类,如果希望Supports能够执行有意义的操作,则需要指定所支持的每个接口,而不是依赖于接口继承. (3认同)