Inheritance is the dynamic variant of composition.
You can dynamically extend objects by adding fields and methods to it's class, but not to composed objects, because they are statically closed. (Well in the good languages. javascript and friends still allow to extend objects, to violate their types).
You can also dynamically mess with the inheritance search path, or fall into the diamond trap. Not with static (or maybe call it lexical) composition.
Composition wastes a lot of space and disallows dynamic extensions, like plugin overrides, test mocking, ... But is very good with proper structural typing, and is a good performance hack, because it doesn't need to chase pointers at runtime, and neither do the inheritance search and linearization dance.
Inheritance is the dynamic variant of composition.
You can dynamically extend objects by adding fields and methods to it's class, but not to composed objects, because they are statically closed. (Well in the good languages. javascript and friends still allow to extend objects, to violate their types).
You can also dynamically mess with the inheritance search path, or fall into the diamond trap. Not with static (or maybe call it lexical) composition.
Composition wastes a lot of space and disallows dynamic extensions, like plugin overrides, test mocking, ... But is very good with proper structural typing, and is a good performance hack, because it doesn't need to chase pointers at runtime, and neither do the inheritance search and linearization dance.