Many others have covered this topic, but I don't agree to most of them. I wanted to capture my opinion about this dilemma here.
If you don't want to read the whole topic, the short answer to the dilemma under question is "it does not matter". If you prefer to find out all the details, then read on.
Composition can be expressed as the following diagram:
In short, Client aggregates different interfaces because it depends on their functionalities. Don't get confused by the "Composition" term - Client class does not really compose interfaces.
Now, let's see what Inheritance means in this context (well, we know what inheritance means, but anyway):
Client inherits from BaseClient, which in turn inherits from Base.
People compare these two approaches when they are trying to design "Client" classes and find things that they think should belong to somewhere else, so that Client simply uses it as pre-existing capability. That's when the dilemma of "Composition vs. Inheritance" appears: should we put the common functionality in a separate interface, or should we put it in a base class?
Recently, I've heard often that composition is a better choice between the two. I must disagree and clarify - it depends on the concrete situation. While I am trying to keep neutral position here, sometimes I feel so "sorry" for inheritance, that I start liking it more. After all, inheritance has (and always had) its purpose, and no one would ever use it if not its purpose and delivered value.
Now, facts and rules for choosing the right strategy:
- Which notion fits better to your class - "Is Of Type" or "Knows About"? Class is of the same kind as its base class. Class knows about capabilities that referenced interfaces provide. Thus, you choose inheritance or composition respectively.
- Does you class already inherit another class? if so, analyze the behavior that you want to separate - maybe it's something "between" the parent and the derived class itself? in such case, you should prefer to go with inheritance by following Intermediate Implementation principle (described earlier).
- Are you going to use the identified behavior in several classes that don't fit into the same inheritance hierarchy? that's still not a strong reason to go with composition. First, think if you are saying "no" to inheritance because of the reusability only. If so, then consider going with both approaches at the same time - follow intuitive way of building inheritance hierarchies, and put the identified capability into separate interface as well. Then, reference this interface from inside the inheritance hierarchies.
- If you have decided that the composition is the way to go, you might consider an alternative of simply putting the repeatable behavior into the static (shared) class if that's simply a utility (helper) functionality. After all, interface has its purpose, you should not abuse it.
- Go with composition if the behavior you identified truly is a separate capability. Interface is a capability, nothing more than that.
I hope you got the idea. I like both approaches, but I don't think any of them is better than the other one without specific context.