Even in this very small example, there are a number of ways we can contrast the two mechanisms.
Of the two techniques, composition is the simpler. Composition clearly indicates what operations are provided, and what are not.
On the other hand, inheritance makes for shorter code, and generally also provides increased functionality, as many more methods may be inherited from the parent class then are actually being used in the given problem. However, this advantage also becomes a disadvantage, as these operations are not documented in the code, and so the programmer must examine the parent classes to see what behavior is provided.
Because there may be many behaviors inherited from the parent, inheritance opens the door to unintended uses.
Because composition encapsulates the older abstraction, it is easier to change the underlying details, for example, swap the List out and replace it with a hash table.
Inheritance permits polymorphism, a topic we will deal with in later chapters. Composition does not.
Understandability is a toss up. Composition makes for longer programs, and hence increases complexity, while inheritance makes for larger hierarchies, and also increases complexity. Which is more problematic differs from situation to situation.
Finally, because composition generally introduces an additional function call, there is a small, very small, execution time advantage for inheritance. Oftentimes other mechanisms, such as function in-lining, can mitigate some of this penalty.