Implementation Inheritance Considered Harmful?

As the years go by and I see more and more painful bugs and convoluted architectures in OOP systems the more convinced I am that implementation inheritance is almost always the wrong answer, and that some kind of trait/mixin/delegation system is superior.

Inheritance sucks partly because you’re expected to extend a class that you didn’t write (or that you at least ostensibly plan to modify independently), by patching into a few of the methods here and there and mucking around with the “protected” innards. This is hardly ever a great long-term design strategy for all but the most carefully designed frameworks (which, in turn, tend to make heavy use of “sealed” classes - i.e. disallowing inheritance!).

I much prefer to put all the “hierarchy” in interfaces, and let the classes themselves be “flat”. That way only _you _need to worry about the internals of your class, and you don’t have to care about what anyone else might do to them without your knowledge.

But even when inheritance works it’s often not desirable. Consider a simple C# GUI dialogue box that asks the user for his name. What’s the interface to this class that a client needs to cope with? Well, if you write it in idiomatic C# by inheriting from Form, it’ll have over 300 public members! 300! For asking the user what his name is! How many of those members do you actually need to use the form? About two or three, at most, I’d guess. So the problem with just blindly extending another class is that each level in the hierarchy you can only add more and more cruft, never remove, and you probably don’t need most of it for your specific version of the class in question. Wouldn’t it make more sense if more specific classes had more specific interfaces?

I’d prefer to write a simple dialogue box by sticking a Form as a member, and write two or three public methods to do the things that people need to do for this specific class. That keeps it simple and obvious. I’m still reusing the heavy-weight and general Form class, but the users of my new class don’t have to see all that. This works fine until you need to use the new dialogue box polymorphically with some other Form-based class.

Really what you’d want is each class to implement a ton of tiny interfaces for each aspect of its behaviour. Most of the time you’d just implement all the interfaces from scratch. Occasionally though, you really do want to just override some tiny part, and you would do so through delegation, not inheritance. You’d keep the “base class” as a member, implement all the interfaces you care about (ideally a small subset of the “base class” interfaces), but forward some of them directly to the “base”. Clearly a language could benefit from supporting this kind of delegation strategy directly, to avoid tedious typing.

I’d like to see a modern, statically typed, OOP language try this delegation/traits based approach to see how it would work in practice. I suspect it would encourage much better programming patterns (customizable and generic components that get specialized and wrapped up into a clean interface for specific instances, rather than relying on inheritance to override bits here and there of some non-generic base class).

As an aside, functional programming in the guise of e.g. Haskell shows how composition and delegation (while implementing type hierarchy “interfaces”) can work beautifully. But I’m sure OOP could be made to work if we just get rid of this unhealthy obsession with inheritance (which was never really the point of it in the first place).

comments powered by Disqus