- COM: No Implementation Inheritance
- The Next Stage: .NET and Visual Basic .NET
- Problems and Solutions
- Conclusion
Problems and Solutions
Anyway, after a while I found not using implementation inheritance in some situations was a mistake. First of all, Microsoft has done a great job with it. This is the most elegant solution of implementation inheritance I have seen and, for example, the versioning partly takes care of the fragile base class scenario. Do you remember the syntactic and semantic versions of the problem I mentioned earlier? The syntactic version is usually not a problem when versioning in .NET is used, so that the subclass still binds to the old superclass. The semantic version of the problem can also be approached by using versioning, but then the subclasses won't benefit from new implementations of their superclasses. If we want to benefit from new superclass versionsand we probably dothen there is the problem of a lot of coupling between the superclass and the subclass, and this isn't solved in .NET. I guess seeing the superclass and subclasses as one entity is one approach, because there is such a strong coupling. Not what we want, but still one approach.
Sure, the problem hasn't gone, but at least it's a little less of a problem.
One example of a situation where I like to use implementation inheritance is when adding a policy to several classes. With the help of implementation inheritance, you can force the subclasses to write code for a method, as long as they inherit from your class. How is that different from implementing an interface? The subclasses could also get some code "forced" on them from the superclass. Let's take a look at how the Template Method pattern (from the book Design Patterns mentioned earlier) can be implemented in Visual Basic .NET. First, let's have a look at the superclass:
Public MustInherit Class SuperClass Public Sub DoStuff() 'This call goes to the subclass. DoEarlyStuff() 'Here is some code that goes for all 'subclasses. '... 'This call goes to the subclass. DoLateStuff() End Sub Protected MustOverride Sub DoEarlyStuff() Protected MustOverride Sub DoLateStuff() End Class
In this specific example, the method DoStuff() can't be overridden, and therefore the implementation is forced on the subclasses. Nevertheless, the subclasses are forced to override the DoEarlyStuff() and DoLateStuff() methods to help with part of the implementation. You can also add the Overridable keyword to the DoStuff() method to make it possible for the subclasses to completely change the implementation.
Following is the implementation of the subclass:
Public Class SubClass Inherits SuperClass Protected Overrides Sub DoEarlyStuff() '... End Sub Protected Overrides Sub DoLateStuff() '... End Sub End Class
Finally, this is how the subclass can be used:
Dim z As New SubClass() z.DoStuff()
Another way to describe the code above is to say that the superclass defines a skeleton of the method to implement, and the subclass adds code for specific parts in the skeleton.
The SubClass is pretty easy to use, isn't it? I think we can consider its implementation as "black box," which is most often something to strive for. However, this is from the perspective of the caller of a subclass. It's not black box as regards the implementation of the superclass if you're about to inherit from the superclass. It's rare to have black box in that situation when implementation inheritance is used. Think of something as simple as an overriding methodshould it call the overridden method in the superclass, or not? The answer is not obvious. It lies in the contract between the superclass and the subclass.