如何在 Delphi 7 中将一个接口转换为另一个接口?

How to cast one interface to another in Delphi 7?

我遇到了以下问题:

我有一个 class,它是使用 Delphi 7 XML 数据绑定向导从 xsd 文件生成的(新建 -> 其他 -> XML 数据绑定).

我需要找到一种方法将方法添加到生成的代码中:

IXMLGlobeSettingsType = interface(IXMLNode)
    ['{9A8F5C55-F593-4C70-85D2-68FB97ABA467}']
    { Property Accessors }
    function Get_General: IXMLGeneralSettingsType;
    function Get_Projector: IXMLProjectorSettingsType;
    function Get_LineMode: IXMLLineDrawingSettingsType;

    { Methods & Properties }
    property General: IXMLGeneralSettingsType read Get_General;
    property Projector: IXMLProjectorSettingsType read Get_Projector;
    property LineMode: IXMLLineDrawingSettingsType read Get_LineMode;

    //procedure SetDefault;   {To be added}
  end;

接口由一个对应的class实现,也是精灵生成的:

TXMLGlobeSettingsType = class(TXMLNode, IXMLGlobeSettingsType)
  protected
    { IXMLGlobeSettingsType }
    function Get_General: IXMLGeneralSettingsType;
    function Get_Projector: IXMLProjectorSettingsType;
    function Get_LineMode: IXMLLineDrawingSettingsType;
  public
    procedure AfterConstruction; override;
  end;

并且为了定义我自己对生成代码的扩展,我定义了以下接口:

IDefaultable = interface
   procedure SetDefault;
end;

使用以下实现 class:

DefaultableXMLGlobeSettingsType = class(TXMLGlobeSettingsType, IDefaultable)
  public
    procedure SetDefault;
  end;

但是,我刚刚意识到 Delphi 7 不允许我将一个接口转换为另一个接口(甚至从一个接口转换为一个对象)。所以下面的代码会引发错误:

defaultSettings : IDefaultable;    
FGlobeSettingsIntf: IXMLGlobeSettingsType; // FGlobeSettingsIntf is in fact a DefaultableXMLGlobeSettingsType

// some code

defaultSettings := FGlobeSettingsIntf as IDefaultable; // error: operator not applicable to this operand type

我几乎被困在这里了。如何解决这个错误? Delphi 7 中有没有一种方法(即使是丑陋的方法)将接口转换为对象,然后再转换回另一个接口。

这就是 Supports 的用途:

if Supports(FGlobeSettingsIntf, IDefaultable, defaultSettings) then begin
  defaultSettings.SetDefault;
end;
defaultSettings := FGlobeSettingsIntf as IDefaultable;
// error: operator not applicable to this operand type

此错误表明 IDefaultable 的定义不包含 GUID。没有 GUID 就不可能查询接口,这就是 as 运算符在此上下文中所做的。

as 运算符与右侧的接口一起使用时,通过调用 IInterface.QueryInterface 来实现。这需要一个 GUID 与界面相关联。

通过在声明 IDefaultable 时添加 GUID 来解决问题。