Keyword trait[−][src]
Expand description
一组类型的通用接口。
trait
就像数据类型可以实现的接口。当类型实现 trait 时,可以使用泛型或 trait 对象抽象地将其视为 trait。
Traits 可以由三个关联项组成:
- 函数和方法
- types
- constants
Traits 也可能包含其他类型参数。这些类型参数或 trait 本身可以受到其他 traits 的约束。
Traits 可以用作标记或承载其他逻辑语义,这些逻辑语义不是通过其项表示的。
当一个类型实现该 trait 时,它承诺遵守其契约。
Send
Sync
和 Sync
是标准库中存在的两个此类标记 traits。
有关 traits 的更多信息,请参见 Reference。
Examples
Traits 使用 trait
关键字声明。类型可以使用 impl
Trait
for
Type
来实现它们:
trait Zero { const ZERO: Self; fn is_zero(&self) -> bool; } impl Zero for i32 { const ZERO: Self = 0; fn is_zero(&self) -> bool { *self == Self::ZERO } } assert_eq!(i32::ZERO, 0); assert!(i32::ZERO.is_zero()); assert!(!4.is_zero());Run
带有关联类型:
trait Builder { type Built; fn build(&self) -> Self::Built; }Run
Traits 可以是泛型,有约束或无约束:
trait MaybeFrom<T> { fn maybe_from(value: T) -> Option<Self> where Self: Sized; }Run
Traits 可以建立在其他 traits 的需求之上。在下面的示例中,Iterator
是 supertrait,而 ThreeIterator
是 subtrait:
trait ThreeIterator: std::iter::Iterator { fn next_three(&mut self) -> Option<[Self::Item; 3]>; }Run
Traits 可以在函数中用作参数:
fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug { for elem in it { println!("{:#?}", elem); } } // u8_len_1,u8_len_2 和 u8_len_3 是等效的 fn u8_len_1(val: impl Into<Vec<u8>>) -> usize { val.into().len() } fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize { val.into().len() } fn u8_len_3<T>(val: T) -> usize where T: Into<Vec<u8>>, { val.into().len() }Run
或作为返回类型:
fn from_zero_to(v: u8) -> impl Iterator<Item = u8> { (0..v).into_iter() }Run
在该位置使用 impl
关键字,函数 writer 可以将具体类型隐藏为实现细节,可以在不破坏用户代码的情况下对其进行更改。
Trait 对象
trait 对象 是另一种实现一组 traits 的不透明值。trait object 实现所有指定的 traits 及其上级特征 (如果有)。
语法如下: dyn BaseTrait + AutoTrait1 + ... AutoTraitN
.
只能使用一个 BaseTrait
,因此无法编译:
trait A {} trait B {} let _: Box<dyn A + B>;Run
这也不是,这是语法错误:
trait A {} trait B {} let _: Box<dyn A + dyn B>;Run
另一方面,这是正确的:
trait A {} let _: Box<dyn A + Send + Sync>;Run
Reference 具有有关 trait 对象,它们的限制以及版本之间的差异的更多信息。
不安全的 traits
某些 traits 可能不安全实现。在 trait 声明的前面使用 unsafe
关键字进行标记:
unsafe trait UnsafeTrait {} unsafe impl UnsafeTrait for i32 {}Run
2015 年版和 2018 年版之间的差异
在 2015 版中,traits 不需要参数模式:
trait Tr { fn f(i32); }Run
此行为在 2018 版中不再有效。