Inheritance was invented as a performance hack (2021)

Performance, Dynamic Dispatch, and GC

  • Several comments question the premise that inheritance is slow. Classic single inheritance with vtables is described as “very fast,” often comparable to C function calls, especially when compilers/JITs devirtualize and inline based on whole‑program or runtime analysis.
  • Others stress that the real cost is polymorphism and pointer chasing: when the exact type can’t be known statically, you pay for vtable lookups, guard checks, and missed inlining, plus cache effects.
  • One thread notes that embedding data (as inheritance or value‑composition) can help GCs and reduce pointer chasing; extra indirections and scattered allocations hurt tracing and cache locality.

Game Engines and Data-Oriented Design

  • Multiple participants note a shift in game development from C++-style OO hierarchies toward ECS and struct‑of‑arrays layouts, driven by cache behavior and the widening CPU–RAM performance gap.
  • Historical recollections: C++ OO was originally adopted in games largely because its inheritance model was seen as the most performant OO variant at the time, but large base classes and deep hierarchies later proved bad for caches and evolution.

Inheritance vs Composition, Traits, and Interfaces

  • Many argue that implementation inheritance is overused and often regretted, while composition plus interfaces/traits usually yield simpler, more flexible designs.
  • “Family tree” hierarchies (Animal → Mammal → Cow) are criticized as rarely matching real problem domains; trait/typeclass-style composition (Rust, Haskell, Go interfaces, Java/C# interfaces with defaults) is praised as a better way to share behavior without rigid trees.
  • Others defend inheritance as a useful, expedient tool in specific cases (UI view hierarchies, dataflow/graph nodes, payment types, intrusive lists), and note that alternatives like delegation, mixins, and macros often exist.

Complexity, Overuse, and Culture

  • There are vivid horror stories of enterprise code with deep inheritance chains, pointless abstractions, and many layers of indirection that ultimately do nothing. Critics see this as cultural: books, “best practices,” and frameworks encouraged over‑abstraction.
  • Counterpoints: you can create unmaintainable messes in any paradigm; OOP and inheritance are not inherently bad, only misused. Some see the current anti‑inheritance stance as another industry fad.

Multiple Inheritance and “Merging Structs”

  • One long subthread debates whether inheritance is a “fundamental” way to merge structures versus simple composition (struct C { a: A, b: B }).
  • One side insists multiple inheritance is inherently problematic (invariants, name clashes, diamond patterns) and that composition is conceptually simpler and easier for humans to reason about.
  • The opposing view claims inheritance is the most direct way to reuse overlapping structure, and that the real limitation is human capacity and tooling for managing the resulting complexity.

Structural Typing and Alternatives

  • Some participants advocate structural typing: being able to pass a value wherever its shape matches an interface, regardless of explicit implements, and using declarations mainly as compile‑time checks.
  • Go, TypeScript, and OCaml/SML modules/functors are mentioned as closer to this ideal; several commenters find structural approaches and protocols more expressive than classic nominal class hierarchies.

Terminology and Conceptual Splits

  • Multiple comments distinguish “implementation inheritance” from “type/interface inheritance,” arguing that conflating them under the single word “inheritance” has caused decades of confusion.