# Static vs dynamic dispatch

> Generics compile a copy per type and call directly; trait objects share one copy and call through a vtable. Pick per call site.

Concept · Rust · https://levelcode.org/concepts/static-vs-dynamic-dispatch

When code calls a method through an abstraction, the program has to decide *which* implementation runs. It can decide at compile time (**static dispatch**) or at runtime (**dynamic dispatch**).

## Static: generics and monomorphization

```rust
fn total_area<S: Shape>(shapes: &[S]) -> f64 {
    shapes.iter().map(|s| s.area()).sum()
}
```

The compiler generates a separate copy of `total_area` for every concrete `S` it's used with (**monomorphization**). Each call is direct and can be inlined, so the abstraction costs nothing at runtime. C++ templates and Rust generics work this way. The costs: longer compile times and larger binaries, and one call site handles one type at a time.

## Dynamic: trait objects and vtables

```rust
fn total_area(shapes: &[Box<dyn Shape>]) -> f64 {
    shapes.iter().map(|s| s.area()).sum()
}
```

A `Box<dyn Shape>` is a fat pointer: one pointer to the data, one to a **vtable** — a table of function pointers for that concrete type. Each call loads the function pointer and jumps through it. One copy of the code handles any mix of types, decided at runtime. Interfaces in Java, C# and [Go](https://levelcode.org/concepts/go-interfaces) dispatch this way for every call.

## Trade-offs

| | Static | Dynamic |
| --- | --- | --- |
| Call cost | Direct, inlinable | Indirect call, no inlining |
| Mixed types in one collection | No | Yes |
| Code size | A copy per type | One copy |
| Restrictions | None | Trait must be dyn compatible (no generic methods, no returning `Self`) |

Default to generics in Rust; reach for `dyn Trait` for heterogeneous collections, plugin registries, or cold code where compile time and binary size matter more than a few nanoseconds. The indirect call itself is cheap; the lost inlining is what costs in hot loops.

Covered with examples in the [traits and generics lesson](https://levelcode.org/roadmaps/rust/traits-and-generics). The design principle behind both is [dependency inversion](https://levelcode.org/concepts/dependency-inversion).
