Specializing an existing type
Inheritance allows a subclass to reuse and specialize behavior from a parent class. It works best when the child really represents a specialized form of the parent and the inherited interface still makes sense.
Overriding and super()
A child class can override a method to provide specialized behavior. super() can call the parent implementation when the child needs to extend rather than completely replace it.
Composition is often an alternative
If one object simply uses another object, composition can be clearer than inheritance. Deep inheritance trees create strong coupling, so prefer simple relationships that remain easy to change.
Practice: create a base notification type with specialized email and SMS implementations, then identify which behavior should remain common.