I have been adding new functionality to a COM Interface, and from what I have read the only way to do it( and keep it backwards compatible ) is to create a new interface that inherits the old interface and add the new methods. I have tried doing this but my hierarchy is already quite complex.
Say this is how my interfaces currently are:
IBaseInterface | IDerivedInterface
and I want to add some functionality to the Base Interface, and it now looks like this:
IBaseOldInterface | IBaseInterface | IDerivedInterface
because I have added this new functionality do i need to create a new IDerivedInterface? I have tried it the way it is at the moment and it doesn't seem to work properly for all cases.
I just want some confirmation really, and an explanation why if possible
I need to further explain what my ideal situation would be and why:
I want to add some methods to the IBaseInterface class that then all of the derived classes can use. What I thought might be possible is this:
IBaseOldInterface / \ IDerivedOldInterface IBaseNewInterface \ / IDerivedNewInterface
I understand that Diamond Inheritance should be avoided but they are only interfaces so I think that will be alright.
having this new structure, when a user requests one of the INewDerivedInterfaces. The query interface will return the correct Interface for that IID, whether that is the INewDerivedInterface or the IOldDerivedInterface.
To add new functionality to
IBaseInterface
, you need to create a new interface, but DO NOT change your existing hierarchy at all. What you can do instead is have the class that implementsIBaseInterface
also implement the new interface as well, eg:That way, any code that wants to use the new
IBaseInterface2
functionality can query anyIBaseInterface
for that interface, and if successful then use the new functionality, eg:Adding methods to the base interface (or replacing it by another that extends it) changes the vtable layout of all derived interfaces, so indeed you need to create new derived interfaces with new IIDs.
There are three ways you can add new functionality to your
IBaseInterface
,IDerivedInterface
interfaces:You add new methods to the bottom of
IDerivedInterface
. The newly built apps aware of these new methods will be able to use them. Earlier built apps will keep safely using old methods. You cannot add methods toIBaseInterface
or reinherit it from another interface because this will shift dependent methods. From the context of your original question I have a feeling that you are changing public interfaces used by a range of external software items, and you don't want your change to cause any issues. If so, you perhaps would want to restrain from going this path, even though it looks simple and doing the job (see below why).You can derive new interface from either
IBaseInterface
orIDerivedInterface
and newly built apps will use it. Beware of necessity to assign new IID to the new interface.INewInterface
in @DavidHeffernan's above) and your COM objects implements just more interfaces. Newly built apps can query new interface and call its methods.Item 3 above is perhaps the typical, easy and convenient way to extend the object. Item 2 makes sense only if you need to keep methods on "main" interface, e.g. for legacy clients such as VB6. Item 1 is a way to quick add stuff without modifying code too much, it does work too - the only catch is that client won't be able to safely detect whether the server is implementing old methods only, or new ones as well.
That does not work. As you have said, to maintain compatibility, you cannot modify an already published interface. But by changing the inheritance you are modifying the interface.
So, you could add the new methods to a new subclass and then you would have this structure:
Or perhaps what you should do is add a new interface which the implementing objects support. So, instead of using inheritance, you simply declare that you implementing class supports multiple interfaces.
In that case you would leave the existing inheritance structure alone, and have something like this:
and then implement the class like this: