00
// inheritance-based vs. interface-based polymorphism & monomorphism
>speak()_
Every implementation in this project calls the same method on the same
cast of characters — Dog, Cat,
PureBreedDog. What changes is how the call gets
resolved: polymorphism is dispatch through an indirection — a
function pointer, a vtable slot, an itable entry, a trait object's fat
pointer. Monomorphism is the compiler or runtime proving that
indirection is unnecessary and removing it. Four languages, four
answers.
01
Notes
Why four languages
The full cross-language comparison: what each part demonstrates, the bytecode/ASM evidence, and a summary table across all four implementations.
NOTEA common misconception
Runtime polymorphism through a base class gets mistaken for an interface often enough to be worth a precise, cited answer — by syntax, semantics, and compiled bytecode.
02
Dispatch table
| Slot | Language | Mechanism | Note | Docs |
|---|---|---|---|---|
| 0x00 | C | hand-rolled fn-ptr | No language-level classes or interfaces — a struct with a function-pointer field, called indirectly. | open docs → |
| 0x01 | C++ | vtable (vptr) | Inheritance and interface (pure abstract class) both compile through the same vptr indirection. | open docs → |
| 0x02 | Java | vtable + itable | invokevirtual vs. invokeinterface — the only language here with a separate bytecode instruction for each. |
open docs → |
| 0x03 | Rust | trait object / monomorphized | No struct inheritance at all — interfaces only, as traits. Generics monomorphize away the indirection entirely. | open docs → |