I use interfaces/abstract base classes for most of my types and don’t often inherit from concrete classes but I’ve recently run into a situation where either inheritance or composition is desired. I’ve been aware of the adage “program to an interface, not an implementation” but recently decided to dig deeper.
I’ve seen arguments against inheritance, and I’ve seen counter arguments but I’m curious as to what other maintainers of large code bases actually do in real life. Is the fear overblown? Do you inherit from concrete classes, or are the inheritance skeptics correct? I’m particularly interested in hearing from those people that work in C++.
Not a C++ guy (have professional experience with big enterprise systems in c#, java, and ruby), but here is my 2 cents anyways
This isn’t a black and white thing.
The problem with inheritance is that it introduces tight coupling. Worse, that coupling is usually around encapsulated state. Changes in super classes can have rippling effects down inheritance hierarchies, creating subtle and hard to predict bugs.
Interface segregation totally sidesteps those issues, because it doesn’t break encapsulation the same way.
The good thing about inheritance is that sometimes you have an object model that really is the same thing, just with a very small change or addition. As long as that change is very clear, not wide reaching in scope, and isn’t an additional constraint (see the circle-ellipse problem), the code reuse will trump the tight coupling.
I stick to composition over inheritance as a rule of thumb, not a law.