1

我一直在向 COM 接口添加新功能,从我所读到的唯一方法(并保持向后兼容)是创建一个继承旧接口并添加新方法的新接口。我试过这样做,但我的层次结构已经很复杂了。

假设这就是我目前的界面:

基础接口
    |
衍生接口

我想向基本接口添加一些功能,现在看起来像这样:

IBaseOld接口
    |
基础接口
    |
衍生接口

因为我已经添加了这个新功能,我需要创建一个新的 IDerivedInterface 吗?我已经按照目前的方式进行了尝试,但它似乎不适用于所有情况。

我真的想要一些确认,并解释为什么如果可能的话

我需要进一步解释我的理想情况是什么以及为什么:

我想向 IBaseInterface 类添加一些方法,然后所有派生类都可以使用这些方法。我认为可能是这样的:

                   IBaseOld接口
                  / \
IDerivedOldInterface IBaseNewInterface
                   \ /
                  IDerivedNew接口

我知道应该避免钻石继承,但它们只是接口,所以我认为没关系。

当用户请求 INewDerivedInterfaces 之一时,具有这种新结构。查询接口将返回该 IID 的正确接口,无论是 INewDerivedInterface 还是 IOldDerivedInterface。

4

4 回答 4

5

那是行不通的。正如您所说,为了保持兼容性,您不能修改已发布的接口。但是通过更改继承,您正在修改接口。

因此,您可以将新方法添加到新子类中,然后您将拥有以下结构:

基础接口
    |
衍生接口
    |
IDerivedInterface2

或者你应该做的是添加一个实现对象支持的新接口。因此,您只需声明您实现的类支持多个接口,而不是使用继承。

在这种情况下,您将不理会现有的继承结构,并拥有如下内容:

IBaseInterface INewInterface
    |
衍生接口

然后像这样实现类:

class TMyObject: public TInterfacedObject, IDerivedInterface, INewInterface
于 2013-07-05T11:35:11.737 回答
3

您可以通过三种方式向IBaseInterface,IDerivedInterface接口添加新功能:

  1. 您将新方法添加到IDerivedInterface. 知道这些新方法的新建应用程序将能够使用它们。早期构建的应用程序将安全地使用旧方法。您不能将方法添加到IBaseInterface另一个接口或从另一个接口重新继承它,因为这将转移依赖方法。 从您最初的问题的上下文来看,我感觉您正在更改一系列外部软件项目使用的公共接口,并且您不希望您的更改引起任何问题。如果是这样,您可能会想要限制走这条路,即使它看起来很简单并且可以完成工作(请参阅下面的原因)。

  2. 您可以从中派生新界面,IBaseInterface或者IDerivedInterface新构建的应用程序将使用它。请注意将新 IID 分配给新接口的必要性。

  3. 你定义了新的接口(比如INewInterface上面的@DavidHeffernan),你的COM对象实现了更多的接口。新建的应用程序可以查询新接口并调用其方法。

上面的第 3 项可能是扩展对象的典型、简单和方便的方法。仅当您需要将方法保留在“主”界面上时,第 2 项才有意义,例如对于 VB6 等旧客户端。第 1 项是一种无需过多修改代码即可快速添加内容的方法,它也确实有效 - 唯一的问题是客户端无法安全地检测服务器是仅实现旧方法还是新方法。

于 2013-07-05T12:23:29.143 回答
0

将方法添加到基本接口(或将其替换为扩展它的另一个)会更改所有派生接口的 vtable 布局,因此您确实需要使用新的 IID 创建新的派生接口。

于 2013-07-05T12:13:32.613 回答
0

要向 中添加新功能IBaseInterface,您需要创建一个新界面,但根本不要更改现有的层次结构。您可以做的是让实现的类IBaseInterface 实现新接口,例如:

type
  IBaseInterface = interface
    ...
  end;

  IBaseInterface2 = interface(IBaseInterface)
    ...
  end;

  IDerivedInterface = interface(IBaseInterface)
    ...
  end;

  TBaseClass = class(TInterfacedObject, IBaseInterface, IBaseInterface2)
    ...
  end;

  TDerivedClass = class(TBaseClass, IDerivedInterface)
    ...
  end;

这样,任何想要使用新IBaseInterface2功能的代码都可以查询IBaseInterface该接口的任何代码,如果成功则使用新功能,例如:

var
  Base2: IBaseInterface2;
begin
  if Supports(AnyBaseOrDerivedInterfacePtr, IBaseInterface2, Base2) then
  begin
    // use Base2 as needed...
  end;
end;
于 2013-07-06T03:38:50.987 回答