20.3 Rust’s Approach: Traits, Composition, and Encapsulation

Rust does not have a class keyword or implementation inheritance as found in C++. Instead, it provides orthogonal features that combine to offer similar capabilities:

  • Structs and Enums: Define custom data types. They hold data.
  • impl Blocks: Associate methods (behavior) with structs and enums, separating data definition from implementation.
  • Traits: Define shared functionality, analogous to interfaces in other languages or abstract base classes with pure virtual functions in C++. They specify method signatures that types must implement to conform to the trait. Traits enable polymorphism. They can also provide default method implementations.
  • Modules and Visibility: Control the visibility of types, functions, methods, and fields. Items are private by default unless marked pub, providing strong encapsulation boundaries at the module level, rather than the class level.
  • Composition: Build complex types by including instances of other types as fields. Functionality is gained by having another type, rather than being another type (inheritance). Rust strongly encourages composition over inheritance.

20.3.1 Code Reuse Strategies in Rust

Instead of class inheritance, Rust promotes code reuse through:

  • Traits with Default Methods: Define shared behavior once within a trait’s default implementation. Any type implementing the trait automatically gets this behavior, which can optionally be overridden.
  • Generics: Write functions, structs, enums, and methods that operate on abstract types constrained by traits. The compiler generates specialized code for each concrete type used (monomorphization), achieving compile-time polymorphism and code reuse without runtime overhead.
  • Composition: Include instances of other types within a struct to delegate functionality or reuse data structures.
  • Shared Functions: Group related utility functions within modules for reuse across the codebase (similar to free functions in C++ namespaces).

These mechanisms offer flexibility without the tight coupling often associated with inheritance hierarchies.