Cover of Refactoring by Martin Fowler, Kent Beck - Business and Economics Book

From "Refactoring"

Author: Martin Fowler, Kent Beck
Publisher: Addison-Wesley Professional
Year: 1999
Category: Computers

🎧 Free Preview Complete

You've listened to your free 10-minute preview.
Sign up free to continue listening to the full summary.

🎧 Listen to Summary

Free 10-min Preview
0:00
Speed:
10:00 free remaining
Chapter 12: Dealing with Inheritance
Key Insight 5 from this chapter

Replacing Inheritance with Delegation

Key Insight

Inheritance, while a powerful mechanism for programming by difference, has inherent limitations. It is a 'one-shot' card, meaning only one axis of variation can be modeled directly; for instance, a person cannot be simultaneously subclassed by age category and income level. Furthermore, inheritance creates tight coupling between classes, making superclass modifications risky for subclasses and complicating distributed development. Delegation offers a robust alternative by allowing multiple independent variations and providing a clearer, less coupled interface between objects. Although some argue against inheritance entirely, a pragmatic approach suggests favoring inheritance initially when semantic conditions are met, then transitioning to delegation if problems arise.

'Replace Subclass with Delegate' is employed when a subclass's behavior would benefit from delegation, especially for dynamic type changes or when multiple variation axes are required. The process involves encapsulating constructor calls with 'Replace Constructor with Factory Function' if many callers exist. An empty delegate class is created, its constructor accepting subclass-specific data and a back-reference to the host superclass. A field is added to the superclass to hold an instance of this delegate. Subclass creation is modified to initialize this delegate field. Subclass methods are moved to the delegate class, with superclass data access routed via the back-reference (`_host`). For overridden methods, dispatch logic is added to the superclass method, conditionally calling the delegate. Methods calling `super()` in the subclass can be handled by extracting the base calculation into a private superclass method or recasting the delegate method as an extension of the base. Methods unique to the subclass are also moved to the delegate, with the superclass gaining dispatch logic that returns `undefined` (in JavaScript) or an error if the delegate is absent. Once all behavior is moved, the subclass is removed.

'Replace Superclass with Delegate' is used when superclass functionality is semantically inappropriate for a subclass (e.g., a `Stack` subclassing `List` exposes non-stack operations) or when the subclass is not truly an instance of the superclass (the 'type-instance homonym' error). This refactoring clarifies the relationship and reduces tight coupling. Mechanics involve creating a field in the subclass that references a new instance of the original superclass (now acting as the delegate). For each superclass element needed, a forwarding function is created in the subclass that calls the corresponding method on the delegate reference. After consistent groups of functions are forwarded and tested, the inheritance link is removed, making the original superclass a component of the new class. This refactoring may subsequently involve 'Change Value to Reference' if the delegate should be a shared reference rather than a unique instance per client.

📚 Continue Your Learning Journey — No Payment Required

Access the complete Refactoring summary with audio narration, key takeaways, and actionable insights from Martin Fowler, Kent Beck.