C++ Records vs Composition vs Inheritance: One Change¶
All three representations implement the same acceleration request. Compare where a reader finds behaviour and where a maintainer edits—not only whether outputs match.
Read Three Implementations¶
In model.hpp:
- RecordWorld owns Seed records and calls a direct function.
- composition::World owns Body values with optional Motion and lifetime.
- inheritance::World owns polymorphic Body objects, choosing UniformBody or AcceleratedBody.
The inheritance example uses two motion variants. Visibility and lifetime remain shared data; we do not manufacture a subclass for every combination to make inheritance look bad.
Composition represents the dependency structurally: an acceleration is owned inside Motion, so a Body without Motion has nowhere to put it.
The input adapter still validates Seed before constructing Body. The two concrete inherited motion constructors also reject incompatible input, including direct construction outside World.
Compare Actual Edit Points¶
| Design | Data and construction | Dispatch | Reader's cost |
|---|---|---|---|
| Records | Optional field in Seed | Branch in advance | Flags and validation |
| Composition | Acceleration in owned Motion | Optional Motion check | Nested values |
| Inheritance | Constructor chooses motion variant | Virtual update_motion | Base contract and override selection |
Shared numerical helpers preserve equations, not identical ownership or dispatch.
The inherited Body::advance retains lifetime ordering after virtual motion. Adding a subclass alone is insufficient if a new requirement changes that shared ordering.
Trace A in Each Version¶
For records, find fields and advance. For composition, follow Body → Motion → acceleration. For inheritance, inspect construction to learn the override, then return to the base for lifetime.
Composition keeps capability ownership explicit. Inheritance can clarify a small family of substitutable algorithms. Records minimise machinery. None is automatically best for every task.
Verify the Comparison¶
The demo ends with:
Tests enumerate 12 valid combinations of movement, visibility, lifetime, and acceleration. Four stationary-acceleration combinations are excluded by the contract.
Full normalised snapshots are compared through several frames. Independently calculated x values provide another oracle. Later identity and ECS worlds participate in the same comparison.
Where Evidence Stops¶
Matching fixtures establishes tested behaviour, not maintainability or speed. Edit maps support judgement; they do not measure developer effort.
Composition here uses optional values, not a plugin registry. Inheritance offers two variants, not arbitrary runtime replacement. No hardware benchmark has been performed.
Exercise¶
Sketch “drag reduces velocity before movement.” Mark input, validation, construction, update, observation, and test edits in all three designs. Is drag an algorithm variant or an independently configurable capability? Define the requirement first.
Next: give persistent selection identity without ECS.