Rust 关联类型
示例
当实现特征的类型和关联的类型之间存在一对一关系时,请使用关联的类型。
有时也称为输出类型,因为这是我们将特征应用到该类型时赋予该类型的项。
创建
trait GetItems { type First; //^~~~定义关联的类型。 type Last: ?Sized; //^~~~~~~~~相关类型也可能受特征约束 fn first_item(&self) -> &Self::First; //^~~~~~~~~~~~使用`Self::`来指代相关的类型 fn last_item(&self) -> &Self::Last; //^~~~~~~~~~~相关类型可以用作函数输出... fn set_first_item(&mut self, item: Self::First); //^~~~~~~~~~~~...输入,以及任何位置。 }
实施方式
impl<T, U: ?Sized> GetItems for (T, U) { type First = T; type Last = U; //^~~分配关联的类型 fn first_item(&self) -> &Self::First { &self.0 } fn last_item(&self) -> &Self::Last { &self.1 } fn set_first_item(&mut self, item: Self::First) { self.0 = item; } } impl<T> GetItems for [T; 3] { type First = T; type Last = T; fn first_item(&self) -> &T { &self[0] } //^您可以参考实际类型而不是`Self::First` fn last_item(&self) -> &T { &self[2] } fn set_first_item(&mut self, item: T) { self[0] = item; } }
引用关联的类型
如果我们确定类型可以在泛型中T实现GetItems,则可以简单地使用它T::First来获取关联的类型。
fn get_first_and_last<T: GetItems>(obj: &T) -> (&T::First, &T::Last) { //^~~~~~~~~指关联类型 (obj.first_item(), obj.last_item()) }
否则,您需要明确告知编译器该类型正在实现的特征
let array: [u32; 3] = [1, 2, 3]; let first: &<[u32; 3] as GetItems>::First = array.first_item(); //^~~~~~~~~~~~~~~~~~~~~~~~~~~~[u32;3]可以实现多种特征,其中许多 //它们提供“First”关联类型。 // thus the explicit "cast" is necessary here. assert_eq!(*first, 1);
约束关联类型
fn clone_first_and_last<T: GetItems>(obj: &T) -> (T::First, T::Last) where T::First: Clone, T::Last: Clone //^~~~~使用where子句按特征约束关联类型 { (obj.first_item().clone(), obj.last_item().clone()) } fn get_first_u32<T: GetItems<First=u32>>(obj: &T) -> u32 { //^~~~~~~~~~~~约束相等类型 *obj.first_item() }