← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Refused Bequest

Code Quality Intermediate
debt(d7/e7/b7/t6)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). detection_hints lists phpstan/psalm but marks automated:no — static analyzers can flag UnsupportedOperationException patterns but the smell itself (semantic mismatch between subclass and parent) requires code review to identify.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). quick_fix says to switch from inheritance to composition — that means every caller relying on the parent type, polymorphic dispatch sites, and type hints across the codebase must change. Not quite architectural rework but well beyond a single-component refactor.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Inheritance hierarchies shape every subclass and consumer; applies_to spans web/cli/queue, and a wrong parent class forces every derived class and client to work around the unwanted interface. Not b9 because it's typically one hierarchy rather than the whole system shape.

t6 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap most devs eventually learn' (t5), nudged to t6 because the misconception is specifically that devs 'fix' it by overriding/nulling methods — the obvious fix is wrong and entrenches the smell. The correct fix (composition) contradicts the inheritance-for-reuse instinct most OOP devs are taught.

About DEBT scoring →

Also Known As

refused inheritance refused bequest smell

TL;DR

A subclass that inherits methods it doesn't need or want, signalling a misused inheritance relationship.

Explanation

Refused Bequest is a code smell where a subclass inherits behaviour from a parent but overrides it to do nothing, throws an exception, or simply ignores it. This is a strong signal that the inheritance hierarchy doesn't reflect a genuine is-a relationship. The fix depends on severity: if the subclass reuses some parent behaviour, extract a sibling class from the parent; if it shares no meaningful behaviour with the parent, replace inheritance with composition. The Liskov Substitution Principle is violated whenever a subclass refuses part of its parent's contract.

Common Misconception

Refused bequest is fixed by moving the unwanted methods to the subclass. The signal is that the subclass should not extend this parent at all — the fix is usually composition rather than inheritance, where the class takes only what it actually needs.

Why It Matters

When a subclass ignores most of its inherited interface, the inheritance relationship is wrong — the subclass should not extend the parent, or the hierarchy needs splitting.

Common Mistakes

  • Subclasses that throw UnsupportedOperationException for inherited methods — the interface contract is broken.
  • Empty method overrides that silence inherited behaviour — the inheritance is wrong, not the method.
  • Using inheritance for code reuse when composition would not impose the unwanted interface.
  • Not using interfaces to define capability subsets — implement only what applies rather than inheriting everything.

Code Examples

✗ Vulnerable
// Child refuses to use methods inherited from parent
class ReadOnlyList extends ArrayList {
    public function add($item): void {
        throw new \RuntimeException('Read-only list cannot be modified');
    }
    public function remove($item): void {
        throw new \RuntimeException('Read-only list cannot be modified');
    }
}
✓ Fixed
// Fix: don't inherit what you can't use — use composition or a separate interface
interface ReadableList {
    public function get(int $index): mixed;
    public function count(): int;
}

class ReadOnlyList implements ReadableList {
    public function __construct(private array $items) {}
    public function get(int $index): mixed { return $this->items[$index]; }
    public function count(): int { return count($this->items); }
    // No add/remove — they simply don't exist here
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 33
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 10 Google 4 ChatGPT 4 Ahrefs 3 Scrapy 3 Perplexity 2 Unknown AI 2 Claude 1 Meta AI 1 Sogou 1
crawler 25 crawler_json 6
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
When a subclass ignores or throws on inherited methods, use composition instead — extract the shared code to a collaborator and inject it rather than inheriting it
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Subclass throwing UnsupportedOperationException on inherited methods; override returning null or empty for parent method that should do something
Auto-detectable: ✗ No phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update


✓ schema.org compliant