Abstract classes provide base implementations that cannot be instantiated directly. They define contracts that derived classes must implement.
Basic Syntax
Abstract Properties
Template Method Pattern
Factory Pattern
Abstract with Generics
Abstract Static Members
Hook Methods
Combining with Interfaces
Protected Abstract
Best Practices
When to Use:
✓ Shared code with enforced contracts
✓ Template method pattern
✓ Factory patterns
✓ Framework base classes
Design:
✓ Keep abstract methods focused
✓ Provide sensible defaults
✓ Document expected behavior
✓ Use protected for internals
Composition:
✓ Prefer composition over inheritance
✓ Combine with interfaces
✓ Use generics for flexibility
✓ Keep hierarchies shallow
Avoid:
✗ Deep inheritance hierarchies
✗ Too many abstract methods
✗ Abstract classes without shared code
✗ Breaking Liskov substitution
Conclusion
Abstract classes combine contracts (like interfaces) with implementation sharing. Use them when you need to share code between related classes while enforcing certain methods to be implemented. They're ideal for template method patterns, factories, and framework base classes. Keep inheritance hierarchies shallow and prefer composition when classes aren't truly related through an "is-a" relationship.