A list containing two different subclasses of your avoiding-copy-paste base class is now most likely a logical error.
A list containing two different subclasses of your avoiding-copy-paste base class is now most likely a logical error.
So don't allow those? Supporting inheritance doesn't mean you have to support heterogeneous lists.
For example, if you call the same function from many locations those locations are now coupled since if you change the function you change all of those locations behaviour. Many times that is desirable, in which case it is good coupling. The exact same rule applies to inheritance.
The only problem with inheritance is that people can use it for classes that weren't written to be base classes, and therefore a ton of bad programmers use it for code reuse without thinking about the contract it is supposed to implement at all. With that in mind, allowing inheritance only for abstract classes isn't an issue at all.
1. Composition is often more explicit than inheritance. Inheritance is overly magic.
2. Composition avoids incidental coupling of methods. With inheritance this is unavoidable.
3. Composition is more difficult to misuse. Both composition and inheritance have their purposes. In the wild, I’ve seen inheritance misapplied much more often than I have seen with composition.