关联类型 associated types

不使用关联类型,使用泛型的情形:

struct Container(i32, i32);
 
trait Contains<A, B> {
    fn contains(&self, _: &A, _: &B) -> bool;
    fn first(&self) -> i32;
    fn last(&self) -> i32;   
}
 
impl Contains<i32, i32> for Container {
    fn contains(&self, number_1: &i32, number_2: &i32) 
    -> bool {
        (&self.0 == number_1) && (&self.1 == number_2)
    }
    fn first(&self) -> i32 { self.0 }
    fn last(&self) -> i32 { self.1 }
}
 
fn difference<A, B, C>(container: &C) -> i32 where
    C: Contains<A, B> {
    container.last() - container.first()        
}

不使用关联类型的话,difference 函数的类型定义会很繁琐。

使用关联类型的情形:

struct Container(i32, i32);
 
trait Contains {
    type A;
    type B;
    fn contains(&self, _: &Self::A, _: &Self::B) -> bool;
    fn first(&self) -> i32;
    fn last(&self) -> i32;   
}
 
impl Contains for Container {
    type A = i32;
    type B = i32;
    fn contains(&self, number_1: &i32, number_2: &i32) 
    -> bool {
        (&self.0 == number_1) && (&self.1 == number_2)
    }
    fn first(&self) -> i32 { self.0 }
    fn last(&self) -> i32 { self.1 }
}
 
fn difference<C: Contains>(container: &C) -> i32 {
   container.last() - container.first() 
}

最佳实践为:如果对于特定的类型,只期望有一个特征的实现,那么使用关联类型,否则使用泛型类型。或者说,在能使用关联类型的地方,尽量都使用关联类型。

如何理解上面的话呢:对于每个要实现特征 Contains 的结构体 Container 来说,如果只需要一个特征的实现,那么使用关联类型。如果在一个结构体中,就需要对特征进行多个不同类型参数的实现,比如要在 Container 中同时实现 i32 类型与 u32 类型的 contains 方法,那么就使用泛型。