This is missing the biggest difference between the two, at least according to me.
In composition (and its on-steroid cousin, delegation), the component/delegate can't "call back" into the aggregating object.
Of course, this additional power can be misused, but it's what should inform the choice between inheritance and composition. Use the least powerful thing that will work — so composition if you don't need to call back into the aggregating object.
> In composition (and its on-steroid cousin, delegation), the component/delegate can't "call back" into the aggregating object.
It can if you design it to take a pointer to the aggregating object. Pass this or self or whatever keyword your language uses to the component/delegate and then it can call back to the aggregating object through an explicit pointer. This is more explicit than calling through the object's vtable, which makes the code easier to read IMO, e.g., foo.bar() instead of bar().
I can't think offhand of an example to illustrate when you would like this "call back" functionality in a way that you can't anticipate when you design the component object. Do you have a killer-app for inheritance?
Any time the component needs to call a method or access data from the aggregate. The kind of thing that happens all the time but the pattern is abstract so there's no killer example.
e.g. the component manages some kind of list, and the content of this list has to be kept in sync with some field in the aggregate.
No example is going to be perfect, because if you have full control over both classes, well then you can always change their interface in a way that it isn't required anymore. One need to consider the reason the thing should be a component in the first place (maybe the pattern is reused in multiple places) and other external and/or historical constraints on the code.
Maybe a plug-in system? It can dynamically register itself with the parent object so that the plug-in is discovered by the system. All the plug-in author would need to do is inherit from the base plug-in class.
In composition (and its on-steroid cousin, delegation), the component/delegate can't "call back" into the aggregating object.
Of course, this additional power can be misused, but it's what should inform the choice between inheritance and composition. Use the least powerful thing that will work — so composition if you don't need to call back into the aggregating object.