【问题标题】:How do I check whether an interfaced object implements another interface?如何检查接口对象是否实现了另一个接口?
【发布时间】:2012-12-29 19:39:09
【问题描述】:

我有这些接口声明:

IListener = interface
  procedure HandleEvent(AEvent: TMyEvent);
end;

IExtendedListener = interface(IListener)
  ['{85A3456A-D5E5-4F37-ABDD-A75A7B3B494C}']  // required by GetInterface
  procedure HandleExtendedEvent(AExtendedEvent: TMyExtendedEvent);
end;

给定实现IListener 的接口引用,我如何检查它是否也实现IExtendedListener?我正在使用代码下面的代码,因为执行if Listener is IExtendedListener then ... 之类的操作是编译时错误。

TSomeClass.Notify(AEvent: TMyExtendedEvent);
var
  Listener: IListener;
  ExtListener: IExtendedListener;
  Obj: TObject;
begin
  for Listener in FListeners do
  begin
    // works but smells funny
    Obj := Listener as TObject;
    Obj.GetInterface(IExtendedListener, ExtListener);
    if Assigned(ExtListener) then
      ExtNotifyee.HandleExtendedEvent(AEvent);
  end;
end;

【问题讨论】:

  • 你的代码没有检查IExtendedListener是否继承自IListener,只是说明通过IListener引用的实例也支持IExtendedListener。它绝不会说明两个接口之间的继承。
  • HandleExtendedEvent 在声明中只有一个参数。为什么要传递 2 个参数?
  • @MarjanVenema,我问这个问题是因为“如果 Listener 是 IExtendedListener 那么”将无法编译。
  • @JeroenWiertPluimers,我相信你错了。我向 TListener 添加了一个 guid,但无法使用 is。不过会很好。

标签: delphi oop interface


【解决方案1】:

您应该使用Sysutils.Supports 来检查特殊接口

uses
  SysUtils;

TSomeClass.Notify(AEvent: TMyExtendedEvent);
var
  Listener    : IListener;
  ExtListener : IExtendedListener;
begin
  for Listener in FListeners do
    if Supports( Listener, IExtendedListener, ExtListener ) then
      ExtListener.HandleExtendedEvent( AEvent );
end;

【讨论】:

  • 我正在清理问题的代码,并留下了对 self 的引用。
  • @LawrenceBarsanti 好的,这对我来说很有意义并且不影响问题:o)
  • 可能他们这样做是为了优化,但他们仍然应该支持接口的“is”和“as”。他们可以检查编译器,如果他们可以优化“as”后跟“is”,并在接口“cast”的结果内部进行一些缓存(在检查期间完成,猜想这是 COM 接口所需要的)
猜你喜欢
  • 2012-04-27
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 2012-03-06
相关资源
最近更新 更多