COM:如果我更改了接口的父节点,我是否需要创建一个新的接口?

时间:2013-07-05 11:28:08

标签: c++ com c++builder

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

说这就是我目前的界面:

IBaseInterface
    |
IDerivedInterface

我想在Base Interface中添加一些功能,现在看起来像这样:

IBaseOldInterface
    |
IBaseInterface
    |
IDerivedInterface

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

我只是想要一些确认,并在可能的情况下解释原因

我需要进一步解释我的理想情况和原因:

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

                   IBaseOldInterface
                  /                 \
IDerivedOldInterface               IBaseNewInterface
                   \               /
                  IDerivedNewInterface

我理解应该避免使用Diamond继承,但它们只是接口,所以我认为这样就可以了。

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

4 个答案:

答案 0 :(得分:5)

这不起作用。正如您所说,为了保持兼容性,您无法修改已发布的界面。但是通过更改继承,您正在修改接口。

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

IBaseInterface
    |
IDerivedInterface
    |
IDerivedInterface2

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

在这种情况下,您将单独保留现有的继承结构,并具有以下内容:

IBaseInterface         INewInterface
    |
IDerivedInterface

然后实现这样的类:

class TMyObject: public TInterfacedObject, IDerivedInterface, INewInterface

答案 1 :(得分:3)

您可以通过三种方式向IBaseInterfaceIDerivedInterface界面添加新功能:

  1. 您可以在IDerivedInterface的底部添加新方法。知道这些新方法的新构建的应用程序将能够使用它们。早期构建的应用程序将安全地使用旧方法。您无法将方法添加到IBaseInterface或从另一个接口重新加载它,因为这将转移相关方法。 从原始问题的上下文中我感觉您正在更改一系列外部软件项使用的公共接口,并且您不希望您的更改导致任何问题。如果是这样,你或许会想要限制走这条路,即使看起来很简单并且正在做这项工作(见下文原因)。

  2. 您可以从IBaseInterfaceIDerivedInterface派生新界面,新构建的应用会使用它。注意必须为新界面分配新的IID。

  3. 您定义了新接口(例如上面@ DavidHeffernan中的INewInterface),您的COM对象只实现了更多接口。新构建的应用程序可以查询新界面并调用其方法。
  4. 上面的第3项可能是扩展对象的典型,简单和方便的方法。只有当你需要在“主要”界面上保留方法时,第2项才有意义。对于诸如VB6的传统客户端。第1项是一种快速添加内容而无需过多修改代码的方法,它也可以工作 - 唯一的问题是客户端无法安全地检测服务器是仅实现旧方法还是新方法。 / p>

答案 2 :(得分:0)

向基接口添加方法(或者用扩展它的另一个方法替换它)会改变所有派生接口的vtable布局,所以你确实需要用新的IID创建新的派生接口。

答案 3 :(得分: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;