Skip to content

Object-Oriented Class Inheritance

Language model — instantiates Controlled Inheritance Propagation

Lets a subclass receive its superclass's fields and methods by default, override chosen methods, and still stand in wherever the superclass is expected.

Object-Oriented Class Inheritance is the archetypal instance of the whole pattern. A subclass declares a superclass and, by that single act, receives all its fields and methods by default, may override specific methods to specialize behavior, and — crucially — remains substitutable for the superclass wherever the latter is expected. Its defining idea is the IS-A contract: inheritance here is not merely code reuse but a typed promise that a subtype can stand in for its supertype without breaking callers. That promise — the Liskov Substitution Principle — is what makes class inheritance a governed propagation channel rather than plain copy-sharing, and it is the relationship every other mechanism in this archetype is, in some sense, generalizing.

Example

A payments team models accounts as Account, with a withdraw(amount) method, and derives SavingsAccount and CheckingAccount. Both inherit balance, deposit(), and statement() unchanged (default propagation), and each overrides withdraw(): savings enforces a monthly withdrawal cap, checking permits an overdraft. Anywhere the system holds an Account reference — a nightly reconciler, a statement generator — it can call withdraw() and get correct, specialized behavior without knowing which subclass it holds. The subclasses are substitutable.

The design turns brittle the moment someone derives FixedTermAccount and overrides withdraw() to throw "not allowed before maturity." Callers written against Account.withdraw() now break on a subtype that cannot honor the base contract — a substitutability violation. That failure is not incidental: making exactly this kind of broken IS-A relationship visible is what the inheritance model, and the substitutability check the compiler runs, are for.

How it works

  • Inherit by default. A subclass names its superclass and receives the superclass's members without restating them.
  • Override in scope. It replaces selected methods — a per-method declaration that specializes behavior for the subclass while leaving everything else inherited.
  • Enforce substitutability. The type system accepts a subclass instance wherever the superclass type is required, and holds overrides to the superclass's contract (compatible signatures, no strengthened preconditions).
  • Extend, don't discard. Constructor and super calls let a subclass build on ancestor behavior rather than throw it away.

Its distinguishing move is the fusion of inheritance with typed substitutability: you do not just receive the parent's code, you receive a compiler-checked promise to be usable as the parent.

Tuning parameters

  • Override granularity — how much a subclass replaces versus extends (calling super to augment, or overriding wholesale). Extension preserves the base contract; wholesale replacement risks breaking it.
  • Sealed / final members — which methods or classes forbid overriding, pinning them as invariants descendants cannot shadow. More sealing protects contracts; less allows specialization.
  • Abstract vs concrete base — whether the superclass can be instantiated or only inherited. An abstract base defines a contract without a default implementation for descendants to accidentally lean on.
  • Single vs multiple inheritance — whether a class may inherit from several parents. Multiple inheritance adds power and the diamond problem (which parent's method wins), the point at which an explicit precedence rule becomes necessary.
  • Depth of specialization — how many levels the hierarchy runs. Deeper chains reuse more but concentrate fragile-base-class risk.

When it helps, and when it misleads

Its strength is expressing a genuine IS-A relationship with compiler-checked substitutability, so shared behavior lives in one place and specializations stay both concise and type-safe. When the domain really is a hierarchy of kinds, nothing states it more directly.

Its failure mode is that implementation inheritance couples a subclass to its parent's internals, so a base change can silently break descendants — the fragile base class problem — and deep hierarchies make behavior hard to locate. The signature misuse is inheriting purely for code reuse where no IS-A relationship exists (a Stack extending a list class just to borrow its methods), which manufactures false substitutability and leaks unwanted operations. The long-standing discipline is to favor composition over inheritance: reach for inheritance only for true subtype relationships, honor the base contract in every override (the Liskov Substitution Principle), and seal what must not be overridden.[1]

How it implements the components

Object-Oriented Class Inheritance realizes the typed-substrate side of the archetype — propagation fused with a substitutability guarantee:

  • default_propagation_rule — a subclass inherits all superclass members by default; you restate nothing, and a base change flows to every subclass that has not overridden it.
  • override_scope_declaration — method overriding is the scoped exception: a subclass declares, per method, exactly what it specializes, leaving the rest inherited.
  • substitutability_check — the type system enforces the IS-A contract, accepting a subclass wherever its superclass is expected and holding overrides to compatible signatures.

It does NOT rank competing declarations by weight the way CSS Cascade and Specificity Rule does, catalog inheritable config keys like Configuration Inheritance Tree, or measure structural smells like Inheritance Lint or Static Analysis; composing behavior from many small units instead of a parent chain is Trait or Mixin Composition Rule.

  • Instantiates: Controlled Inheritance Propagation — the canonical typed instance of the pattern: default inheritance, scoped override, and enforced substitutability in one construct.
  • Sibling mechanisms: Inheritance Lint or Static Analysis · CSS Cascade and Specificity Rule · Configuration Inheritance Tree · Effective Configuration Diff · Lineage Impact Analysis Report · Override Expiry Workflow · Prototype Delegation Chain · Trait or Mixin Composition Rule · Schema Extension and Override Check · Permission Inheritance with Explicit Denial · Policy Inheritance Matrix · Platform Variant Option Model · Template Clause Override Register

Notes

Class inheritance binds relationships at compile time and type-checks them; a prototype delegation chain (a sibling mechanism) achieves similar sharing at runtime through a live chain of objects, trading static guarantees for the freedom to alter the lineage while the program runs. Same archetype, different point on the static-versus-dynamic axis — worth naming so the two are not conflated.

References

[1] The Liskov Substitution Principle (Barbara Liskov) holds that objects of a subtype must be usable anywhere the supertype is expected without breaking correctness. "Favor composition over inheritance" is the companion guideline, popularized by the Gang of Four's Design Patterns, for when a true IS-A relationship does not hold.