Start here. This is the direct spoken answer to practice first.
Why this question matters
Inheritance is appropriate when the derived type is behaviorally substitutable for the base type, not merely when two types share fields or methods. Callers using the base contract should continue to work correctly with every subtype.
I use inheritance only when the subtype can preserve the base type's behavioral contract. I ask whether it can honor the base type's accepted inputs, guarantees, and failure behavior. If a ReadOnlyDocument inherits from EditableDocument but throws for Save, the hierarchy advertises a capability it cannot preserve. Shared fields such as Id and Name can be composed into a value or helper without claiming an is-a relationship.