Refused Bequest¶
Flag an inheritance edge as broken when a subclass accepts a parent's implementation but refuses part of its contract — stubbing, throwing, or silently mishandling inherited members — because that refusal is exactly the Liskov substitutability violation the is-a declaration promised not to make.
Core Idea¶
Refused bequest is the object-oriented design code smell — named and catalogued by Kent Beck and Martin Fowler in Refactoring (1999) — in which a subclass inherits methods, fields, or contractual obligations from its superclass that it does not want, cannot fulfil, or honours only by violating the parent's behavioural contract. The subclass overrides inherited methods to throw NotSupportedException, return null or sentinel values, or leave method bodies empty; it uses inheritance to acquire the implementation it wants while rejecting the contract that inheritance implies.
The structural commitment that makes this a failure rather than a mere style choice is the Liskov Substitution Principle: a correctly formed subclass must be substitutable for its supertype everywhere the supertype is used, without breaking the contract clients depend on. A subclass that refuses part of the inherited contract is not substitutable — client code that calls an inherited method on a reference typed as the superclass will encounter a throw, a null, or silent semantically incorrect behaviour when it receives an instance of the refusing subclass. The inheritance edge declared "this is a kind of that," but the subclass's behaviour contradicts the declaration for the refused portions.
The failure's characteristic origin is the use of inheritance for code reuse rather than subtype classification. A developer finds that a parent class contains useful implementation — a lookup mechanism, a persistence layer, a collection — and inherits from it to acquire that implementation cheaply, without checking whether the full contractual bundle the parent defines is appropriate for the child. The easy parts of the bundle (the shared implementation) are accepted; the incompatible parts (method obligations that do not apply to the child) are refused. Beck and Fowler's canonical example is Square extends Rectangle: a square cannot independently set width and height, so it must refuse the independent setWidth and setHeight setters that Rectangle's contract provides. The paired corrective refactorings are Replace Inheritance with Delegation — the subclass holds the parent as an internal object and delegates only the methods it can honour — and Extract Superclass to a narrower shared interface that represents only what the subclass can actually commit to.
Structural Signature¶
Sig role-phrases:
- the inheritance edge — an
extendsrelationship declaring "the subclass is-a kind of the superclass" - the bequeathed contract — the full bundle of methods, fields, and behavioural obligations the subtype-of declaration implies
- the subclass's actual obligations — what the child can genuinely honour, narrower than the bequeathed contract
- the refusal signature — the visible mark of the gap: empty overrides,
NotSupportedExceptionthrows, null/sentinel returns, or silent contract violations (four spellings of "no") - the LSP standard — the Liskov Substitution Principle, the contract against which the gap is a defect rather than a style choice
- the substitutability break — the latent fault: a client holding the subclass through a superclass-typed reference and calling a refused member encounters the throw, null, or silent wrong behaviour
- the reuse-versus-classification root cause — the prior question the
extendskeyword hides: was inheritance taken for genuine subtype classification (whole contract applies) or for cheap implementation reuse (only part of the bundle fits) - the remedy routing — the deterministic fix selected by that branch: Replace Inheritance with Delegation (reuse-not-classification) or Extract Superclass to the narrower honourable contract (contract merely too broad)
What It Is Not¶
- Not a matter of style or taste. The empty override, the
NotSupportedException, the null-returning stub are the visible signature of a correctness defect, not an aesthetic preference. The gap between what is inherited and what the subclass can honour is an LSP violation latent in any client that holds the subclass through a superclass-typed reference — so the refusal signature is the proof that substitutability fails, not just an oddity to tolerate. - Not the Liskov Substitution Principle itself. LSP is the normative standard a correct subtype must meet; refused bequest is one characteristic symptom of an LSP violation, visible in the code. The principle states the rule; the smell names the recognizable way the rule is broken — they are the standard and a sign of its breach, not the same thing.
- Not diagnosed at the superclass. Refused bequest is a defect of the subclass — the child that rejects part of the parent's contract. An over-broad superclass (a god class) may produce refused bequests in its children, but that breadth is diagnosed at the parent; the refusal, and the refactoring it routes to, are located at the subclass that cannot honour what it inherited.
- Not an indictment of inheritance as such. Inheritance is a legitimate subtype-classification construct; the failure is using an
extendsedge for cheap implementation reuse when only part of the contractual bundle fits. A genuine is-a edge whose subclass honours the whole contract is fine — the root cause is reuse-not-classification, which is why the remedy is delegation or a narrower superclass, not abolishing inheritance. - Not generic interface or impedance mismatch. Those are substrate-independent connector-shape problems; refused bequest is the specifically object-oriented case where the connector is the inheritance relationship and the mismatch is contract-shaped — the inherited contract is the wrong shape for what the subclass can commit to. The OO framing of inheritance-as-classification is the load-bearing, craft-specific piece.
- Not literally present outside OO programming. An organizational role "inheriting" obligations from its parent category, or a bylaw inheriting constraints from a parent ordinance, can be narrated as a refused bequest, but the apparatus that makes it a defect — LSP, the Fowler smell catalogue, the named refactorings, the
extendsedge with its automatic bundle — does not transfer; only the metaphor does. The genuinely portable structure is the parent classification/contract mismatch, not this named smell.
Scope of Application¶
Refused bequest lives within object-oriented programming, across the language families, inheritance flavors, and idiomatic settings where an extends edge declares "is-a" while the subclass contradicts the declared contract for some members; its reach is bounded to that craft. The cross-domain narrations (a role or bylaw "inheriting" obligations it cannot meet) are metaphor — the LSP-and-refactoring apparatus does not transfer — and the genuinely portable structure belongs to the parent classification/contract and interface-mismatch primes.
- Class hierarchies in mainstream OO languages — the canonical
Square extends Rectangle, where the square must refuse the independentsetWidth/setHeightsetters the rectangle's contract provides. - Framework subclassing — a custom widget inheriting dozens of base-class lifecycle hooks, most stubbed empty because the widget does not participate in those phases.
- Object-relational mapping — a value object inheriting entity machinery (lazy loading, change tracking, identity equality) it cannot honour.
- GUI control hierarchies — a read-only display control inheriting edit, focus, and input methods from an editable parent and refusing or stubbing them.
- Adjacent type-system constructs — the same craft pattern borrowed into typeclass hierarchies, interface inheritance, and schema-extension contracts within programming-language design.
Clarity¶
Naming refused bequest converts a diffuse reviewer's discomfort with an inheritance hierarchy into a precise, pointable diagnostic. The empty override, the NotSupportedException, the null-returning stub are no longer isolated oddities to be tolerated case by case; they are the visible signature of one defect, and a reviewer can point to them and say the subclass is refusing its bequest, so the inheritance edge is wrong. The label's clarifying move is to drive a wedge between two things the extends keyword fuses: what is inherited (the methods, fields, and contractual obligations the parent declares) and what the subclass can actually honour. Holding those apart makes the gap itself the object of attention, and it explains why the smell is a correctness problem and not a matter of taste — the gap is exactly an LSP violation waiting to surface in any client that holds the subclass through a superclass-typed reference.
The concept also sharpens the why behind the misuse and points at the fix. Without it, "we inherited to reuse the lookup code" sounds like prudent economy; with it, the sharp question becomes whether inheritance was chosen for subtype classification (a genuine is-a, where the whole contract applies) or merely for implementation reuse (where only some of the bundle fits) — and that diagnosis routes directly to a named remedy rather than to vague rework. Recognizing reuse-not-classification tells the designer to Replace Inheritance with Delegation (hold the parent as an internal object, expose only the honourable methods) or Extract Superclass down to the narrower contract the child can commit to. The smell-name and the refactoring-name form a paired vocabulary: spotting the refusal does not merely flag a problem, it selects the move that dissolves it.
Manages Complexity¶
Reviewing an inheritance hierarchy, absent this concept, means holding a bundle of separately-named worries in mind at once and re-deriving them for every subclass: is this a Liskov violation, will it break a client holding the subclass through a parent-typed reference, is the superclass contract too broad, is the hierarchy over-coupled to a framework, why is this override empty, why does that one throw. Each subclass is its own multi-front investigation. Refused bequest compresses the whole cluster to a single per-member question asked once across the hierarchy: for each inherited method, field, or obligation, can the subclass honour it as the parent's contract requires? The empty override, the NotSupportedException, the null-returning stub, the silently wrong result are not four separate oddities to weigh independently — they are one signature, four spellings of the same answer "no." The sprawl of code-quality concerns collapses onto one yes/no per inherited member.
What the reviewer tracks is therefore a single tally — the set of refused members on each inheritance edge — and the qualitative outcomes read straight off whether that set is empty. An edge with no refusals is a genuine subtype, substitutable, safe under any parent-typed client; an edge with even one refusal is an LSP violation latent in exactly the clients that call the refused member through the supertype, and the severity is just the reach of those members. The reviewer need not re-prove substitutability from first principles or trace every client by hand: the presence of the refusal signature is the proof that substitutability fails, with the refused set marking precisely where.
The compression also fixes the remedy's branch structure, which is what makes the diagnostic actionable rather than merely descriptive. A non-empty refusal set forces one prior question — was the inheritance taken for subtype classification (a true is-a, whole contract applies) or for implementation reuse (only part of the bundle fits) — and the answer routes deterministically to a named move: reuse-not-classification selects Replace Inheritance with Delegation (hold the parent as an internal object, expose only the honourable methods); a contract merely too broad selects Extract Superclass down to what the child can commit to. So a designer reading a hierarchy does not face an open-ended redesign space; they read the refused set, classify the edge's intent on a two-way branch, and the refactoring is selected for them. A diffuse, multi-concern audit reduces to one per-member predicate, a single tally, and a binary routing to a closed set of corrective moves.
Abstract Reasoning¶
Refused bequest licenses a set of reasoning moves in object-oriented design review, all turning on the wedge it drives between what is inherited (the methods, fields, and contractual obligations the parent declares) and what the subclass can actually honour, with the Liskov Substitution Principle as the standard the gap is measured against.
The signature diagnostic move reads a code signature as direct evidence of a contract failure and locates it precisely. An empty override, a NotSupportedException, a null-or-sentinel return, or a silently incorrect result is not weighed as an isolated oddity but recognized as one signature — four spellings of the same answer "no" to the per-member question can the subclass honour this inherited method, field, or obligation as the parent's contract requires? The presence of the refusal signature is the proof that substitutability fails; the reasoner does not re-derive LSP compliance from first principles but reads the violation off the code, with the refused set marking exactly which members break the contract.
The predictive move forecasts where and for whom the latent fault will surface. Because the defect is an LSP violation, the reasoner predicts that client code holding the subclass through a superclass-typed reference and calling a refused member will encounter the throw, the null, or the silently wrong behaviour — and that clients calling only honoured members, or holding the subclass through its own type, will not. The severity is read off the reach of the refused members: a widely-called refused method (an altitude recorder consumed by a migration analyzer that receives a flightless bird) is a serious latent crash, an obscure one a minor one. The reasoner thus anticipates the breakage site from the refused set without tracing every client by hand.
The root-cause classification move asks the prior question the extends keyword hides: was the inheritance taken for subtype classification (a genuine is-a, where the whole contract applies) or merely for implementation reuse (where a developer wanted the parent's lookup, persistence, or collection machinery and accepted the easy parts of the bundle while refusing the incompatible ones)? Recognizing reuse-not-classification reframes "we inherited to reuse the lookup code" from prudent economy into the diagnosis of the smell, and pins the cause to the misuse of an inheritance edge as a reuse device.
The remedy-routing move is deterministic rather than open-ended: a non-empty refused set, once classified on that two-way branch, selects a named refactoring. Reuse-not-classification routes to Replace Inheritance with Delegation — the would-be subclass holds the parent as an internal object and exposes only the methods it can honour, so the incompatible contract is never bequeathed and never refused. A contract merely too broad routes to Extract Superclass down to the narrower interface the child can actually commit to. The reasoner predicts the effect of each move (substitutability restored because the refused members are no longer inherited through a subtype edge) and chooses between them by the edge's intent. The smell-name and the refactoring-name form a paired vocabulary, so spotting the refusal does not merely flag a problem but selects the move that dissolves it — and the whole audit reduces to a per-member predicate, a single tally of refusals per edge, and a binary routing into a closed set of corrective moves.
Knowledge Transfer¶
Within object-oriented programming refused bequest transfers as mechanism. The per-member predicate (for each inherited method, field, or obligation, can the subclass honour it as the parent's contract requires?), the recognition that the refusal signature — empty override, NotSupportedException, null/sentinel return, silent wrong result — is the proof that substitutability fails, the prediction of where the latent LSP fault surfaces (clients holding the subclass through a superclass-typed reference and calling a refused member), the root-cause classification (subtype classification versus implementation reuse), and the deterministic remedy routing (reuse-not-classification → Replace Inheritance with Delegation; contract-too-broad → Extract Superclass) carry intact across the OO settings that share the substrate. They apply unchanged across language families (Java, C++, C#, Python, Smalltalk, Ruby), across inheritance flavors (single, multiple, mixin, trait), and across the idiomatic cases — Square extends Rectangle, framework widget subclassing with dozens of refused lifecycle hooks, ORM value objects inheriting entity machinery they cannot honour, read-only controls inheriting edit/focus/input methods. The corrective vocabulary (delegation, interface segregation, composition-over-inheritance) ports across all of these, and the borrowings into adjacent type-system constructs (typeclass hierarchies, interface inheritance, schema extension) are still the same craft pattern inside programming-language design. The transfer is mechanical here because each is the same substrate — an inheritance edge declaring "is-a" while the subclass contradicts the declared contract for some members — so the smell signature and the named refactorings refer to the same machinery throughout.
Beyond OO programming the transfer is predominantly case (A) metaphor, with a genuine case (B) residue underneath. The cross-domain "extras" the source gestures at — an organizational role "inheriting" obligations from its parent category, a zoning bylaw inheriting constraints from a parent ordinance, a curriculum inheriting requirements, an infrastructure plan inheriting a template's commitments — can be narrated as refused bequests, but the apparatus that gives the smell its force (the Liskov Substitution Principle, the Fowler code-smell catalogue, the named refactoring moves, the extends edge with its automatic contractual bundle) does not transfer; only the metaphor does. Calling a role's mismatched inherited duties "a refused bequest" borrows the vivid OO shape while dropping the substitutability machinery that makes it a correctness defect rather than a loose analogy, so it should be marked as analogy. Underneath that metaphor, though, the structure that genuinely recurs travels via the parent primes the smell decomposes into: classification and contract (a category membership implies a contractual bundle), the violation of behavioural substitutability (the Liskov_substitution_principle / behavioural-subtyping idea), and interface_mismatch (the inherited contract is the wrong shape for what the entity can honour). Those parents do recur across domains — any system where assigning a thing to a category imports obligations it cannot meet exhibits the same mis-fit — and that is the honest cross-domain lesson to carry: a classification that bequeaths a contract its member cannot honour is an interface/contract mismatch, fixed by narrowing the contract or composing rather than classifying. What stays strictly home-bound is everything that makes it refused bequest: the inheritance-as-classification framing, the LSP standard, the four-spelling refusal signature, and the paired smell-and-refactoring vocabulary are OO-craft furniture, and stripping the jargon dissolves the term into classification + contract + LSP-violation + interface_mismatch plus that OO-specific framing — which is exactly why it is a domain-specific abstraction (a Fowler-catalogue diagnostic, sibling to primitive obsession, god class, lazy class) and not a prime. The cross-domain reach belongs to those parents; "refused bequest," as named, carries object-oriented-craft baggage that does not and should not travel. (See Structural Core vs. Domain Accent.)
Examples¶
Canonical¶
Beck and Fowler's Square extends Rectangle is the defining case. A Rectangle class exposes setWidth(w) and setHeight(h) as independent operations; its contract implicitly promises that after r.setWidth(5); r.setHeight(4) the area is 20. A Square is mathematically a rectangle, so a developer writes class Square extends Rectangle. But a square cannot vary width and height independently, so Square must override the inherited setters — typically making setWidth(5) silently also set height to 5. Now consider client code that receives a Rectangle reference, calls setWidth(5) then setHeight(4), and asserts the area is 20. Given a genuine Rectangle it passes; given a Square instance the second call has also reset the width, area is 16, and the assertion fails. The subclass acquired the rectangle's fields and machinery but could not honour its independent-dimension contract.
Mapped back: Square extends Rectangle is the inheritance edge; independent setWidth/setHeight is the bequeathed contract that the subclass's actual obligations cannot meet. The overridden setter that silently mutates both dimensions is the refusal signature (a silent contract violation). The failing area assertion through a Rectangle reference is the substitutability break against the LSP standard.
Applied / In Practice¶
The Java standard library ships a real, widely-discussed refused bequest in its unmodifiable and immutable collections. Collections.unmodifiableList(...) and List.of(...) return objects that are java.util.List — they satisfy the interface type — yet they cannot honour the mutator half of the List contract. Calling add, remove, set, or clear on them throws UnsupportedOperationException at runtime rather than modifying the list. Code written against a plain List reference, reasonably assuming it can append an element, compiles fine but crashes when handed an immutable instance. The JDK adopted this design as a pragmatic compromise (avoiding a separate mutable/immutable type split throughout the collections framework), but it is a textbook substitutability hazard: the "is-a List" declaration overpromises.
Mapped back: An immutable list's "is-a List" relationship is the inheritance edge; the mutator methods are the part of the bequeathed contract it cannot fulfil. The UnsupportedOperationException throw is the refusal signature in its most literal spelling. A caller appending through a List reference hits the substitutability break, and the root cause is the reuse-versus-classification tension — reusing the List interface for read-only data.
Structural Tensions¶
T1: Inheritance for reuse versus for classification (the intent the extends keyword hides). extends fuses two intents the language gives one keyword: acquiring the parent's implementation (its lookup, persistence, or collection machinery) and asserting a subtype classification (an is-a where the whole contract applies). Refused bequest is exactly what results when a developer reaches for the first and unwittingly commits to the second — taking the easy parts of the bundle while refusing the incompatible ones. The tension is structural, not accidental: the very convenience that makes inheritance an attractive reuse device is what silently imports the contractual obligation the reuse motive never intended to honour. Cheap reuse and contractual commitment ride on the same keyword, so the economy of "just inherit the lookup code" is precisely the trap. Diagnostic: Was this extends edge taken to reuse the parent's implementation, or to assert that the child genuinely is-a kind of the parent with its whole contract applying?
T2: Diagnosed at the subclass versus caused at the superclass (where the defect lives). Refused bequest is a defect of the child — the subclass that rejects part of the inherited contract, marked by the empty override or the thrown exception. But its cause frequently lives at the parent: an over-broad superclass (a god class) bundling obligations no reasonable child can honour will manufacture refused bequests across all its subclasses. So the smell is located and named at one end of the edge while the disease may sit at the other. The tension for the reviewer is that fixing the refusal at the subclass (delegation, or a narrower extracted superclass) treats the symptom where it shows, but if the superclass contract is the real problem, per-child patches proliferate while the god class keeps producing new refusals. Reading the refused set tells you the edge is broken; it does not tell you which end to repair. Diagnostic: Is this a narrow contract mismatch fixable at the subclass, or the recurring signature of one over-broad superclass that should itself be split?
T3: Correctness defect versus pragmatic compromise (when refusing the bequest is the accepted design). The refusal signature is the proof that substitutability fails — a real LSP violation, not a matter of taste. Yet the JDK ships a textbook refused bequest deliberately: Collections.unmodifiableList and List.of are-a List that throw UnsupportedOperationException on the mutator half, a design the library adopted to avoid a separate mutable/immutable type split threading through the whole collections framework. So a genuine correctness hazard was accepted as the lesser cost. The tension is that the "clean" fix — segregating the interface so no child inherits what it cannot honour — carries its own price: type proliferation, weakened polymorphism, more machinery. Refused bequest is thus not always a bug to eliminate but sometimes a defect to knowingly tolerate, and the smell's binary "refusal = broken edge" cannot by itself weigh that trade. Diagnostic: Is the cost of the substitutability hazard here greater than the cost of the type split or interface segregation that would eliminate it?
T4: Replace Inheritance with Delegation versus Extract Superclass (routing the remedy). A non-empty refused set forces a two-way branch, and the routing is not always obvious. Reuse-not-classification routes to Replace Inheritance with Delegation — the would-be subclass holds the parent as an internal object and exposes only the methods it can honour. A contract merely too broad routes to Extract Superclass down to the narrower interface the child can commit to. The tension is that the same refused set can be produced by either cause, and choosing wrong is costly: delegating when the edge was a genuine (if over-broad) is-a discards real polymorphism the design needed; extracting a superclass when the child never was a subtype papers over a category error with a shared interface. The refusal signature localizes the break but underdetermines which named move dissolves it — that turns on the edge's intent, which the code does not record. Diagnostic: Does the child genuinely belong to a narrower supertype (Extract Superclass), or was it never a subtype at all and only wanted the implementation (Replace Inheritance with Delegation)?
T5: Latent fault versus present defect (severity is the reach of the refused member). Every refusal is an LSP violation in principle, but its danger is not uniform — it is exactly the reach of the refused members. A widely-called refused method reached through a superclass-typed reference (an altitude recorder consumed by a migration analyzer that receives a flightless bird) is a serious latent crash; an obscure one almost never invoked polymorphically is nearly harmless. The tension is that the per-member predicate returns a clean binary — honoured or refused — while the actual risk is continuous and depends on client behaviour the class cannot see. So treating every refusal as an equal defect over-audits harmless edges, while treating "it never crashes in practice" as safe ignores that the fault is dormant, not absent, waiting for the first client that holds the subclass through its supertype and calls the refused member. Diagnostic: How far does the refused member reach through superclass-typed references — is the violation a live crash path or a dormant one no client currently exercises?
T6: Autonomy versus reduction (a named OO smell or an instance of its parents). "Refused bequest" is a Fowler-catalogue diagnostic with craft-specific furniture: the inheritance-as-classification framing, the LSP standard, the four-spelling refusal signature (empty override, thrown exception, null return, silent wrong result), and the paired smell-and-refactoring vocabulary. None of that travels outside OO programming — a role or bylaw "inheriting" obligations it cannot meet can be narrated as a refused bequest, but the apparatus that makes it a correctness defect does not follow, so such use is metaphor. What genuinely recurs across substrates is the parents the smell decomposes into: classification and contract (category membership implies a contractual bundle), the behavioural-substitutability violation (the Liskov idea), and interface_mismatch (the inherited contract is the wrong shape for what the member can honour). The tension is between a sharply useful in-situ code diagnostic and the recognition that its cross-domain lesson already belongs to those parents. Diagnostic: Resolve toward classification/contract/interface_mismatch when a non-OO system assigns obligations a member cannot meet; toward refused bequest when auditing an actual inheritance edge for substitutability.
Structural–Framed Character¶
Refused bequest sits toward the framed end of the structural–framed spectrum — best read as framed-leaning, deep in framed territory as a named craft defect but held just off the pole by an unusually mechanical, binary diagnostic and the clean structural parents it decomposes into. On evaluative_weight it patterns framed: "refused bequest" convicts — to name it is to find a correctness defect, an LSP violation to be refactored away, not to neutrally describe a mechanism; the entry insists the refusal signature "is the proof that substitutability fails," a verdict of breakage, not a style note. On human_practice_bound it is strongly framed: the concept is constituted by the practice of object-oriented programming and dissolves the instant that practice is removed — the extends edge, the automatic contractual bundle, and the substitutability standard are all software-craft constructs, and outside OO programming (a role or bylaw "inheriting" obligations) only the metaphor survives, the correctness-defect apparatus gone. On institutional_origin it is a pure artifact of a tradition: Beck and Fowler's Refactoring catalogue, the Liskov Substitution Principle, the named refactorings (Replace Inheritance with Delegation, Extract Superclass), and the four-spelling refusal signature are all furniture of a specific software-engineering tradition, sibling to primitive obsession and god class, not distinctions nature marks.
On vocab_travels it is framed: the operative vocabulary — inheritance edge, bequeathed contract, NotSupportedException, substitutability, the smell-and-refactoring pairing — is pinned to the OO substrate and keeps its content only there. On import_vs_recognize the transfer is bimodal exactly as the entry argues: within OO programming the smell moves as recognition of the same mechanism across language families, inheritance flavors, and idioms; beyond it, narrating an organizational role's mismatched duties as "a refused bequest" is import-by-analogy that borrows the vivid shape while dropping the LSP machinery that makes it a defect.
What holds it framed-leaning rather than at the pole is that its diagnostic is unusually mechanical and deterministic — a clean per-member yes/no predicate (can the subclass honour this inherited member?), a refusal signature that is the proof, a single tally per edge, and a binary routing into a closed set of named remedies — which gives it more structural, algorithmic ballast than a judgment-laden verdict. But that machinery is craft-internal and does not make "refused bequest" itself travel. The portable structural skeleton is classification-implies-contract mismatch — assigning an entity to a category imports a contractual bundle the entity cannot honour, breaking behavioural substitutability. That skeleton is substrate-neutral, but it is precisely what refused bequest instantiates from its umbrella parents — classification and contract (category membership implies a contractual bundle), the Liskov/behavioural-subtyping idea, and interface_mismatch (the inherited contract is the wrong shape for what the member can honour) — not what makes "refused bequest" itself travel. The cross-domain reach (any system where categorizing a thing imports obligations it cannot meet) belongs to those parents; refused bequest keeps for itself the OO-craft cargo — the inheritance-as-classification framing, the LSP standard, the refusal signature, the paired refactoring vocabulary — that stays home. Its character: a normatively charged, OO-craft-constituted defect verdict whose mechanical binary diagnostic gives it a structural edge, portable only in the classification/contract-mismatch skeleton it borrows from its parents and frames as a substitutability bug.
Structural Core vs. Domain Accent¶
This section decides why refused bequest is a domain-specific abstraction and not a prime, and it carries the case for its domain-specificity — no other section does.
What is skeletal (could lift toward a cross-domain prime). Strip the object-oriented craft away and a thin relational structure survives: assigning an entity to a category imports a contractual bundle, and when the entity cannot honour part of that bundle, its category membership over-promises and behavioural substitutability breaks. The portable pieces are abstract — a classification act, a contract the classification implies, an entity whose actual obligations are narrower than the contract, and the resulting mismatch between what was promised by membership and what can be delivered. That classification-implies-contract-mismatch skeleton is genuinely substrate-neutral, which is why the smell decomposes into the parent primes named below and why any system that categorizes a thing and thereby imports obligations it cannot meet exhibits the same mis-fit; but it is the core it shares, not what makes refused bequest distinctive.
What is domain-bound. Everything that makes it refused bequest in particular is object-oriented-craft furniture and none of it survives extraction. It presupposes the OO inheritance-as-classification framing: the extends edge that fuses implementation reuse with subtype assertion and bequeaths an automatic contractual bundle. On that sit the worked apparatus — the Liskov Substitution Principle as the standard the gap violates; the four-spelling refusal signature (empty override, NotSupportedException throw, null/sentinel return, silent wrong result) that serves as proof of the break; the reuse-versus-classification root-cause branch; and the paired smell-and-refactoring vocabulary (Replace Inheritance with Delegation, Extract Superclass) drawn from Beck and Fowler's Refactoring catalogue, where it sits as a sibling of primitive obsession, god class, and lazy class. These are the craft vocabulary, instruments, and canonical cases (Square extends Rectangle, the JDK's unmodifiable List) of one software-engineering tradition. The decisive test: remove OO programming — as when an organizational role or a bylaw "inherits" obligations it cannot meet — and the LSP standard, the refactoring catalogue, and the extends bundle do not follow; only the metaphor survives, and what is left is a looser category/contract mismatch, no longer this named correctness defect.
Why this does not clear the prime bar. A prime is a relational structure whose vocabulary travels and whose cross-domain transfer is recognition of the same mechanism, not analogy. Refused bequest's transfer is bimodal. Within object-oriented programming it travels intact — across language families (Java, C++, C#, Python, Smalltalk, Ruby), inheritance flavors (single, multiple, mixin, trait), and idioms (framework widget subclassing, ORM value objects, read-only controls) — because each supplies the one thing it needs, an inheritance edge declaring "is-a" while the subclass contradicts the contract, so the per-member predicate, the refusal signature, and the named refactorings all move as recognition of the same machinery. Beyond OO it travels only by analogy: narrating a role's or a bylaw's mismatched inherited duties as "a refused bequest" borrows the vivid shape while dropping the substitutability apparatus that makes it a correctness defect. And when the bare structural lesson — a classification that bequeaths a contract its member cannot honour is fixed by narrowing the contract or composing rather than classifying — is genuinely wanted cross-domain, it is already carried, in more general form, by the parents the smell decomposes into: classification and contract (category membership implies a contractual bundle), the Liskov_substitution_principle / behavioural-subtyping idea (substitutability of a subtype for its supertype), and interface_mismatch (the inherited contract is the wrong shape for what the entity can honour). The cross-domain reach belongs to those parents; refused bequest, as named, keeps the inheritance-as-classification framing, the LSP standard, the refusal signature, and the paired refactoring vocabulary that should stay home.
Relationships to Other Abstractions¶
Current abstraction Refused Bequest Domain-specific
Parents (3) — more general patterns this builds on
-
Refused Bequest is a kind of Code Smell Domain-specific
Refused Bequest is the code-smell species whose stubs, throws, or ignored inherited members provide defeasible evidence that inheritance was used for reuse despite a broken subtype contract.It inherits the diagnostic trace, hidden design hypothesis, contextual test, predicted consequence, and refactoring probe. The child adds an inheritance edge, Liskov substitutability, refused contractual members, and replacement by delegation or a narrower shared superclass.
-
Refused Bequest is a kind of Interface Mismatch Prime
Refused Bequest is the object-oriented interface mismatch in which a subtype's offered behavior fails the supertype contract clients are entitled to require.Interface Mismatch supplies two locally workable sides, a required contract seam, and a gap between offered and required behavior. Refused Bequest inherits that structure and specifies the seam as an inheritance promise: the subclass reuses implementation while stubbing, throwing from, or mishandling members the supertype contract requires.
-
Refused Bequest presupposes Liskov Substitution Principle Domain-specific
Refused Bequest presupposes LSP because the smell is precisely a subclass refusing inherited obligations that substitutability requires it to honor.The subclass accepts an inheritance edge yet stubs, throws from, or silently violates some inherited operation. That conduct is only diagnosable as refused bequest relative to the supertype-client contract and LSP's requirement that every promised behavior survive substitution.
Hierarchy paths (13) — routes to 8 parentless roots
- Refused Bequest → Code Smell → Evidence → Provenance → Traceability → Observability
- Refused Bequest → Interface Mismatch → Interface → Boundary
- Refused Bequest → Liskov Substitution Principle → Substitutability → Compatibility
- Refused Bequest → Liskov Substitution Principle → Substitutability → Modularity → Decomposition
- Refused Bequest → Liskov Substitution Principle → Substitutability → Abstract Data Type → Information Hiding → Abstraction
- Refused Bequest → Liskov Substitution Principle → Substitutability → Containerization → Information Hiding → Abstraction
- Refused Bequest → Code Smell → Evidence → Provenance → Attestation → Authentication
- Refused Bequest → Liskov Substitution Principle → Substitutability → Abstract Data Type → Information Hiding → Boundary
- Refused Bequest → Liskov Substitution Principle → Substitutability → Abstract Data Type → Interface → Boundary
- Refused Bequest → Liskov Substitution Principle → Substitutability → Containerization → Information Hiding → Boundary
- Refused Bequest → Liskov Substitution Principle → Substitutability → Containerization → Interface → Boundary
- Refused Bequest → Code Smell → Evidence → Provenance → Traceability → Transformation → Function (Mapping)
- Refused Bequest → Code Smell → Evidence → Provenance → Custody Transfer → State and State Transition → Phase Space
Not to Be Confused With¶
- God class (over-broad superclass). A sibling Fowler smell diagnosed at the parent — a class bundling more obligations than any reasonable child can honour. A god class produces refused bequests across its subclasses, but the god-class defect lives at the superclass while refused bequest is located at the subclass that rejects part of what it inherited. Tell: is the breadth of the contract the problem (parent → god class), or the child's inability to honour an otherwise-reasonable contract (child → refused bequest)?
- Interface Segregation Principle violation. The SOLID neighbour where a fat interface forces implementers to depend on methods they do not use. Refused bequest is the specifically inheritance-edge version — the connector is an
extendsbundle carrying implementation plus contract, not a bare interface — and its remedy space includes delegation, not just splitting the interface. Tell: is the mismatch on a pure interface a client must implement, or on an inherited implementation-plus-contract bundle a subclass claims to be a kind of? - Fragile base class problem. The neighbouring hazard where changes to a superclass silently break subclasses that depended on its internals. This runs parent→child (the base breaks the derived); refused bequest runs child-against-parent (the derived contradicts the base's contract). Opposite direction of breakage. Tell: did a base-class change break the subclass, or does the subclass refuse a stable part of the base's contract?
- An abstract method /
NotImplementedException-by-design. An abstract base or template-method stub that throws to signal "a concrete subclass must supply this" — a deliberate, contract-honouring extension point, not a refusal. The identical throw is a refused bequest only when the type advertises "is-a" and a client, holding it through the supertype, is entitled to call the member and instead hits the throw. Tell: is the throw an unfilled abstract slot the type never promised to satisfy, or the refusal of a concrete contract the type's is-a declaration promised to keep? - Primitive obsession / lazy class (sibling catalogue smells). Other entries in Beck and Fowler's smell catalogue — over-use of primitives for domain concepts, a class doing too little to justify itself. They share the catalogue and the review setting but name entirely different defects; only refused bequest keys on inheritance-contract substitutability. Tell: does the concern turn on an
extendsedge and LSP, or on data representation / a class's weight? - The parent primes it decomposes into (
classification,contract,interface_mismatch, Liskov/behavioural-subtyping). The substrate-neutral structure — category membership imports a contractual bundle a member cannot fully honour — that any non-OO system (a role or bylaw "inheriting" duties it cannot meet) exhibits. Those parents, not "refused bequest," carry the cross-domain lesson; borrowing the name outside OO is analogy. Tell: strip the LSP standard, the refactoring catalogue, and theextendsbundle, and only classification-implies-contract-mismatch remains — treated fully in a later section.
Neighborhood in Abstraction Space¶
Refused Bequest sits in a sparse region of the domain-specific corpus (81st percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely.
Family — Overgeneralization & Rule Misapplication (5 abstractions)
Nearest neighbors
- Liskov Substitution Principle — 0.86
- Primitive Obsession — 0.83
- Lazy Class — 0.82
- Declared Equivalence Mapping — 0.82
- Data Class — 0.82
Computed from structural-signature embeddings · 2026-07-12