Refused Bequest: What It Costs and How to Fix It
A subclass that inherits methods and data it does not need or want, violating the Liskov Substitution Principle.
What It Is
Refused Bequest occurs when a subclass inherits from a parent but only uses a fraction of the inherited interface. The subclass may override methods to throw exceptions, leave inherited methods empty, or simply ignore large portions of the parent's API. This is a sign that the inheritance hierarchy is wrong: the subclass is not truly a specialisation of the parent. The Liskov Substitution Principle states that substituting a subclass for its parent should not break the program, but Refused Bequest violates this by making the subclass an unreliable stand-in.
Why It Costs Money
Developers who call parent-type methods on the subclass get surprising results (exceptions, no-ops, or wrong behaviour). These bugs are particularly expensive because they only manifest at runtime and often only in specific code paths.
The inheritance hierarchy becomes misleading documentation. New developers assume the subclass behaves like its parent, make changes based on that assumption, and introduce subtle bugs.
Refactoring the parent class is dangerous because changes may break subclasses in unexpected ways. Teams become afraid to improve the parent, leading to stagnation.
Specific Cost Mechanisms
- ●Runtime surprises: methods that throw or silently fail when called on the subclass, costing 2-6 hours per incident
- ●False assumptions: new developers misunderstand the hierarchy, introducing bugs that pass code review
- ●Parent stagnation: fear of breaking subclasses prevents improving shared code
Estimated Annual Cost
Cost per instance by team size and codebase size. Based on $120,000 average developer salary. See full methodology.
| Team Size | Small (<50k LOC) | Medium (50k-200k) | Large (200k+) |
|---|---|---|---|
| 3 devs | $2,000 | $4,800 | $9,600 |
| 5 devs | $3,300 | $8,000 | $16,000 |
| 10 devs | $5,000 | $12,000 | $16,000 |
| 20 devs | $6,600 | $16,000 | $16,000 |
How to Detect It
Specific rules and thresholds for automated detection. See full tool comparison.
Overriding to do nothing, abstract class with no abstract methods
Indirect: subclass much smaller than parent suggests refused bequest
Parent with no abstract methods may indicate over-inheritance
Directly detects unused inherited members
Refactoring Patterns
Proven techniques to eliminate this smell. See all refactoring patterns.
Replace Inheritance with Delegation
The subclass only needs a few methods from the parent
Extract Superclass
Some siblings share behaviour but the current parent is too broad
Push Down Method/Field
Inherited members are only used by one subclass