Conditional Method Implementations
#![allow(unused)] fn main() { // No trait bounds on the type definition. pub struct Value<T>(T); // Instead bounds are put on the implementations for the type. impl<T: std::fmt::Display> Value<T> { fn log(&self) { println!("{}", self.0); } } // alternatively impl<T> Value<T> { // Specifies the trait bound in a where expression fn log_error(&self) where T: std::error::Error, { eprintln!("{}", self.0); } } }
-
When authoring a type with generic parameters, we can write implementations for that type that depend on what the parameters are or what traits they implement.
-
These methods are only available when the type meets those conditions.
-
For things like ordered sets, where you’d want the inner type to always be
Ord, this is the preferred way of putting a trait bound on a parameter of a type.We don’t put the definition on the type itself as this would cause downstream issues for everywhere the type is mentioned with a generic parameter.
We can maintain invariants just fine with conditional method implementations.