在 Delphi 中使用接口是不是需要 GUID?

Posted

技术标签:

【中文标题】在 Delphi 中使用接口是不是需要 GUID?【英文标题】:Are GUIDs necessary to use interfaces in Delphi?在 Delphi 中使用接口是否需要 GUID? 【发布时间】:2011-02-28 20:22:21 【问题描述】:

官方文档说它们是可选的。我知道 COM 互操作需要每个接口的唯一标识符,但我看到的每个接口示例都有一个 GUID,无论它是否与 COM 一起使用?如果 GUID 不与 COM 一起使用,包含 GUID 有什么好处吗?

【问题讨论】:

【参考方案1】:

仅当您需要您的界面为compatible with COM 时。

不幸的是,这还包括使用isas 运算符和QueryInterfaceSupports 函数——缺少这些函数是相当有限的。因此,虽然不是严格要求,但使用 GUID 可能更容易。否则,您只剩下相当简单的用法:

type
  ITest = interface
    procedure Test;
  end;

  ITest2 = interface(ITest)
    procedure Test2;
  end;

  TTest = class(TInterfacedObject, ITest, ITest2)
  public
    procedure Test;
    procedure Test2;
  end;

procedure TTest.Test;
begin
  Writeln('Test');
end;

procedure TTest.Test2;
begin
  Writeln('Test2');
end;

procedure DoTest(const Test: ITest);
begin
  Test.Test;
end;

procedure DoTest2(const Test: ITest2);
begin
  Test.Test;
  Test.Test2;
end;

procedure Main;
var
  Test: ITest;
  Test2: ITest2;
begin
  Test := TTest.Create;
  DoTest(Test);
  Test := nil;

  Test2 := TTest.Create;
  DoTest(Test2);
  DoTest2(Test2);
end;

【讨论】:

不对;请参阅@eagle 的回答。在没有 GUID 的情况下使用非 COM 接口的唯一方法是不安全的硬转换。 如果我在上面添加的示例中有任何不安全的地方,请告诉我,谢谢。 @Craig:我不确定接口是否存在“不安全的硬强制转换”,因为编译器仍然需要一些方法来定位正在使用的接口的接口表。 @Mason,他们有。这曾经是使用 IProviderSupport 的唯一方法。 VCL 源代码就是这样做的,至少在 D6 时代是这样。 @TOndrej,您的代码是安全的,因为您永远不会更改为不相关的接口(实际上是多重继承),这是您使用接口的很大一部分原因。想象一个与ITest 没有子类型关系的IFoo。假设实现类型支持两者,您如何将 ITest 的引用转换为 IFoo 的引用。您需要 GUID 才能安全地执行此操作。【参考方案2】:

我注意到某些方法,例如Supports(用于确定类是否符合特定接口)要求您先定义 GUID,然后才能使用它们。

This page 用以下信息确认:

注意:SysUtils 单元提供了一个 称为 Supports 的重载 函数 上课时返回真或假 类型和实例支持 由 a 表示的特定接口 GUID。 Supports 函数用于 德尔福的方式是 运营商。显着差异 是支持功能可以采取 作为正确的操作数 GUID 或 与 a 关联的接口类型 GUID,而 is 和 as 取名称 一种类型。有关更多信息 is 和 as,请参阅类引用。

这里有一些interesting information about interfaces,其中指出:

为什么需要一个接口 唯一可识别?答案是 简单:因为 Delphi 类可以 实现多个接口。当一个 应用程序正在运行,必须 成为一种将获得指针的机制 从一个适当的接口 执行。 找到的唯一方法 如果一个对象实现了一个 接口并获取指向的指针 该接口的实现是 通过 GUID

强调在两个引号中。

阅读整篇文章还会让您意识到,QueryInterface(需要 GUID)在幕后使用是出于引用计数等原因。

【讨论】:

另外,值得注意的是,尝试使用带有接口的 isas 强制转换涉及其中一个调用(我忘记了),所以你需要一个 GUID也这样做。 所以简短的回答是,虽然 GUID 是可选的,但不使用它们会限制您对接口的操作。 需要使用Supports 函数是迄今为止我为接口定义 GUID 的唯一原因。 “确定对象是否实现接口并获得指向该接口实现的指针的唯一方法是通过 GUID。”为什么不直接查询对象的方法并检查以确保对象中存在具有这些名称的方法?好老鸭打字?您不会在其他语言中看到这种 GUID 废话。

以上是关于在 Delphi 中使用接口是不是需要 GUID?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi判断某个类是否实现了某个接口

Delphi GUID[2] 获取GUID值的方式

delphi生成GUID

如何检索系统上网络适配器的 GUID?

Delphi中避免使用ClassName判断对象的类型

Delphi 的 64 位 DLL c/c++ 接口