The first and foremost concept surrounding an interface is that it is a form of contract between the client using the interface and the object implementing it. This contract means that when a client has a pointer to an interface, the client can successfully call every member function in that interface. In other words, when an object implements an interface, it must implement every member function to at least return E_NOTIMPL. This means that after a client has obtained a pointer to an interface from a call to QueryInterface, it no longer has to ask the object whether the functions in that interface are callable—they are. The functions may not actually do anything, but they can be called. That is the nature of the contract.
Given that, there are four other important points about interfaces:
Just because a class supports one interface, there is no requirement that it support any other. Interfaces are meant to be small contracts that are independent of one another. There are no contractual units smaller than interfaces. However, specifications or protocols such as OLE Documents and OLE Controls are higher contractual units than interfaces; objects must implement a related set of interfaces as defined by the specification of a certain prototype. See "Class, Type, and Prototype" on page 64. It is true that all compound document objects or OLE controls will always implement the same basic set of interfaces, but those interfaces themselves do not depend on the presence of the other interfaces. It is instead the clients of those objects that depend on the presence of all the interfaces.
The encapsulation of functionality in objects accessed through interfaces makes COM/OLE an open, extensible system. It is open in the sense that anyone can provide an implementation of a defined interface and anyone can develop a client that uses such interfaces. It is extensible in the sense that new or extended interfaces can be defined without changing existing clients or components, and those clients that understand the new interfaces can exploit them on newer components while continuing to interoperate with older components through the old interfaces. Still better is the fact that no underlying changes to COM or OLE are required to support your own custom interface designs, as we'll see in Chapter 6. Because of that, you can extend the system without ever having to involve Microsoft, a big change from previous service architectures in which any change in features meant a change to the system API. You don't have to wait for Microsoft any longer—you can innovate as fast and as often as you want and control your own destiny!