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()
}