Skip to main content

Traits

Generics vs. Associated Types

use associated type to bind a type to a trait implementation; get the type uniquely determined by the trait implementation.

e.g.

Add trait binds Output type to a trait implementation so that when a RHS type is given then can determine the return type of add() uniquely.

pub trait Add<RHS = Self> {
type Output; // associated type

fn add(self, rhs: RHS) -> Self::Output;
}
impl Add<u32> for u32 {
type Output = u32;

fn add(self, rhs: u32) -> u32 {
// [...]
}
}

impl Add<&u32> for u32 {
type Output = u32;

fn add(self, rhs: &u32) -> u32 {
// [...]
}
}
// let result: u32 = 1u32 + 1u32
// let result: u32 = 1u32 + &1u32

if Output is generics instead of associated type like below,

pub trait Add<RHS = Self, Output> {
fn add(self, rhs: RHS) -> Output;
}

we can get implementations for RHS, which could result in multiple result types. using associated type disallows to do so.

impl Add<u32, u32> for u32 {
fn add(self, rhs: u32) -> u32 {
// [...]
}
}

impl Add<u32, &u32> for u32 {
fn add(self, rhs: u32) -> &u32 {
// [...]
}
}
// let result: u32 = 1u32 + 1u32
// let result: &u32 = 1u32 + 1u32