Inheritance and Abstract Classes
Inheritance models an “is-a” relationship and allows a subclass to specialize a base class. An abstract class cannot be instantiated directly and may require subclasses to implement abstract members. Interfaces are often preferable when only a contract is needed and shared implementation is unnecessary.
Avoid deep inheritance hierarchies that make behavior hard to trace. Composition—building a behavior from smaller collaborators—is often easier to test and evolve. If a base class has many protected hooks or subclasses need to know internal details, reconsider whether the abstraction is too tightly coupled.
Abstract base class
abstract class NotificationChannel {
abstract send(message: string): Promise<void>;
protected format(message: string): string {
return `[Bytes4Dev] ${message}`;
}
}
class ConsoleChannel extends NotificationChannel {
async send(message: string): Promise<void> {
console.log(this.format(message));
}
}💡 The abstract method defines a requirement for subclasses. The protected helper shares implementation while restricting access to the class hierarchy.
Key Takeaways
- Abstract classes can combine contracts and shared behavior.
- Interfaces are suitable for contracts without implementation.
- Prefer composition over unnecessarily deep inheritance.
Knowledge Check
Can an abstract class be instantiated directly?