COM: No Implementation Inheritance
As you know, Visual Basic .NET supports implementation inheritance. That is, a class can inherit from a superclass, and thereby the subclass derives the implementation of the methods in the superclass. The subclass can also override some of the methods and extend the behavior by adding more methods, for example. This must be nirvana! Or is it? Actually, I was pretty negative when I first started to play with it, but let's step back and allow me to tell you a little story. It starts a couple of years ago, around the time when VB4 came out.
VB4 started to look a bit object-oriented, but it lacked the possibility of implementation inheritance. Without implementation inheritance it was useless, in many developers' opinions. I longed for support for implementation inheritance and couldn't see any reason why it wasn't added, until I read Clemens Szyperski's book, Component Software: Beyond Object-Oriented Programming (Addison-Wesley, 1998, ISBN 0-201-17888-5). He talks a lot about the "fragile base class scenario"that is, when a superclass has to be changed, it will greatly affect both the subclasses and the consumersand why for a long time researchers had found implementation inheritance to be evil, especially for building large systems. From that point on, I was happy with the decision to exclude implementation inheritance from COM (and thereby VB4VB6). I used user-defined interfaces a lot, and as a result separated the implementation from the interface.
By the way, user-defined interfaces à la COM is known as the "Bridge pattern" in the book Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley, 1995, ISBN 0-201-63361-2).
Before we move on, I'd like to discuss briefly the fragile base class scenario, of which there are both syntactic and semantic versions. The syntactic problem is that subclasses need a recompile when the superclass interface is changed. The semantic version of the problem is how a subclass can survive evolution of the implementation in the superclass. (We'll come back to this in a few minutes.)