The most widespread use of traits is for writing generic functions or types. For
example, the following signature describes a function for consuming any iterator
yielding items of type
A to produce a collection of
fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
Iterator trait is specifies an interface that a type
explicitly implement to be used by this generic function.
enumtype is generic over some type parameter
T, values of type
Twill be laid out inline in the
enum, without any indirection.
Precise types. Because generic give a name to the specific type implementing a trait, it is possible to be precise about places where that exact type is required or produced. For example, a function
fn binary<T: Trait>(x: T, y: T) -> T
is guaranteed to consume and produce elements of exactly the same type
cannot be invoked with parameters of different types that both implement
Tis a type parameter, it stands for a single actual type. So for example a
Vec<T>contains elements of a single concrete type (and, indeed, the vector representation is specialized to lay these out in line). Sometimes heterogeneous collections are useful; see trait objects below.
Generic types are a form of abstraction, which entails a mental indirection: if
a function takes an argument of type
T bounded by
Trait, clients must first
think about the concrete types that implement
Trait to understand how and when
the function is callable.
To keep the cost of abstraction low, favor widely-known traits. Whenever possible, implement and use traits provided as part of the standard library. Do not introduce new traits for generics lightly; wait until there are a wide range of types that can implement the type.