20.10 Summary

Rust offers powerful features to achieve the goals traditionally associated with Object-Oriented Programming—encapsulation, polymorphism, and code reuse—but employs a different set of tools compared to class-based languages like C++:

  • Encapsulation: Achieved via modules and the visibility system (pub), controlling access primarily at the module boundary. Struct fields are private by default, promoting controlled access through methods.
  • Code Reuse: Favors composition over inheritance. Reuse is also facilitated by generics and traits with default method implementations.
  • Polymorphism:
    • Compile-time Polymorphism (Static Dispatch): The preferred approach in Rust, achieved through generics and trait bounds. Monomorphization yields high performance comparable to non-polymorphic code.
    • Runtime Polymorphism (Dynamic Dispatch): Enabled by trait objects (dyn Trait). Uses fat pointers and vtables, conceptually similar to C++ virtual functions, suitable for scenarios requiring runtime flexibility or heterogeneous collections.
  • Alternatives: Enums provide a robust alternative for handling closed sets of related types, offering compile-time exhaustiveness checks and often better performance than trait objects.
  • Key Differences from C++ OOP: No implementation inheritance (class Derived : public Base), no protected visibility, encapsulation is module-based, strong preference for composition and compile-time polymorphism.

By combining structs, enums, impl blocks, traits, generics, and modules, Rust provides a flexible and safe system for building abstractions and managing complexity, aiming to avoid some common pitfalls of classical inheritance while retaining the core benefits of object-oriented design principles.