5

我是一名 Java 开发人员,最近被迫戴上 Delphi 开发人员的帽子。

就像在这种情况下的典型情况一样,我最终尝试在 Delphi 中做一些事情,同时仍然使用我的“Java”思维方式,当它们不起作用时我会感到困惑。

今天的问题是接口的概念。在 Java 中,我可以定义一个接口,给它一些方法,然后声明一个实现该接口的类。

我曾尝试在 Delphi 中做同样的事情,但我的手指被烫伤了。我声明了一个扩展 IInterface 的接口。但是在实现该接口时,我遇到了一些未声明的方法(QueryInterface、_AddRef、_Release)的未实现方法错误。

一个小小的 Google 告诉我,我需要扩展 TInterfacedObject 而不是 TObject。这让我感到不安,因为它表明我不能简单地将接口添加到某个第三方类,除非该类最终扩展了 TInterfacedObject。

但是现在,当需要设置我的接口对象 .Free 时,我得到了 EInvalidPointer 异常。

结果,我开始得出结论,接口这个词对 Java 开发人员和 Delphi 开发人员的含义完全不同。

精通两种语言的人可以启发我了解差异吗?

干杯。

4

2 回答 2

8

Delphi 中的接口类型具有三个功能:

  1. 是一种通用语言特性,用于从 Java 中的接口类型的实现中抽象出接口。
  2. 构成 Delphi 的 COM 支持的核心(一个 DelphiIInterface与 COM 相同IUnknown)。
  3. 在非垃圾收集环境的上下文中提供一种形式的自动内存管理。

这些功能在概念上是不同的,并且正如您所发现的,当组合在同一功能中时,会产生不太理想的结果:

  • Delphi 中的每个接口最终都必须从IInterface/继承IUnknown,因此,具有三个IUnknown方法(AddRefRelease-QueryInterface前两个被重命名_AddRef,并且_Release在 Delphi 中阻止您直接调用它们)。如果希望能够在运行时查询接口,还需要给它一个 GUID。
  • TInterfacedObject_AddRef作为一个方便的基类存在,尽管如果你实现,_Release和你自己就不必使用它QueryInterface(这样做涉及标准模式,所以并不难)。原则上,您还可以通过返回-1前两个来禁用引用计数(TComponent例如,该类执行此操作)。
  • 尽管如此,当通过接口访问对象时,编译器总是会插入_AddRef和调用。_Release这使得通过对象和接口引用访问同一个对象经常是不安全的,即使在 return时_AddRef也是如此。_Release-1
于 2013-09-30T18:03:54.873 回答
3

区别在于垃圾收集器。Java 有一个。但是在 Delphi 中,您必须自己控制对象。

_AddRef 和 _Release 的创建使这变得简单。当一个变量开始指向你的对象时,Delphi 调用_AddRef。在那里,您必须增加对该对象的引用计数。当代码中的变量“松散”链接到对象 Delphi 调用 _Release。在那里你必须减少计数器。当您的计数器变为 0 时,您可以为此对象调用 destroy() Self.Destroy()

希望这可以帮助。

PS。TInterfacedObject 已经实现了这些方法,这就是 Google 和 Delphi 文档建议使用 TInterfacedObject 的原因。

于 2013-09-30T16:52:08.313 回答