Refused Bequest
Inheritance is powerful, but it's often misused. "Refused Bequest" happens when a subclass inherits from a parent but doesn't actually want or use the functionality it inherited. It's like a child refusing their parent's inheritance.
Technically, the code compiles. But conceptually, it's wrong. If a Dog class inherits from Chair just to reuse a getLegCount() method, but throws an exception for sit(), that’s Refused Bequest. It often implies the hierarchy is wrong.
Signs of the Smell
- A subclass throws "Not Supported" exceptions for inherited methods.
- A subclass leaves inherited methods empty.
- Clients of the subclass code have to know not to call certain parent methods.
Reasons of the Smell
Reuse over Correctness: You wanted to reuse some code in the parent class, so you extended it, even though the "Is-A" relationship (Liskov Substitution Principle) doesn't hold.
Refactoring Recipe
- Push Down Method / Field
- Replace Inheritance with Delegation
Push Down Method / Field
If the parent class has logic that only some children use, maybe that logic belongs in those specific children, not the parent.
Before:
class Animal {
void fly() { ... } // Dogs can't fly!
void bark() { ... }
}
class Dog extends Animal {
// inherits fly() which is weird
}
After:
class Animal {
void bark() { ... }
}
class Bird extends Animal {
void fly() { ... } // Moved down to where it belongs
}
class Dog extends Animal {
// No longer refuses 'fly'
}
Replace Inheritance with Delegation
If you only need to use one method from a class, don't inherit from it. Just put an instance of that class inside your class and call it.
Before:
class MyList extends ArrayList {
// I only want to use 'add' and 'size', but I inherited 100 other methods!
}
After:
class MyList {
private List list = new ArrayList(); // Delegate
public void add(Object o) {
list.add(o);
}
}