实现
语法
实现 :
InherentImpl | TraitImplInherentImpl :
impl
GenericParams? Type WhereClause?{
InnerAttribute*
AssociatedItem*
}
TraitImpl :
unsafe
?impl
GenericParams?!
? TypePathfor
Type
WhereClause?
{
InnerAttribute*
AssociatedItem*
}
实现 是一个将条目与实现类型关联起来的条目。实现使用关键字 impl
定义,并包含属于被实现类型的实例或静态类型的函数。
有两种类型的实现
- 固有实现
- trait 实现
固有实现
固有实现被定义为 impl
关键字、泛型类型声明、名义类型的路径、where 子句以及关联条目的括号集合的序列。
名义类型被称为实现类型,而关联条目是关联到实现类型的关联条目。
固有实现将包含的条目与实现类型关联起来。
它们不能包含关联类型别名。
关联条目的路径是到实现类型的任何路径,后跟关联条目的标识符作为最终路径组件。
一个类型也可以有多个固有实现。实现类型必须与原始类型定义在同一个 crate 中定义。
pub mod color { pub struct Color(pub u8, pub u8, pub u8); impl Color { pub const WHITE: Color = Color(255, 255, 255); } } mod values { use super::color::Color; impl Color { pub fn red() -> Color { Color(255, 0, 0) } } } pub use self::color::Color; fn main() { // Actual path to the implementing type and impl in the same module. color::Color::WHITE; // Impl blocks in different modules are still accessed through a path to the type. color::Color::red(); // Re-exported paths to the implementing type also work. Color::red(); // Does not work, because use in `values` is not pub. // values::Color::red(); }
Trait 实现
Trait 实现 的定义方式类似于固有实现,不同之处在于可选的泛型类型声明之后是 trait,然后是关键字 for
,然后是名义类型的路径。
该 trait 被称为已实现 trait。实现类型实现了已实现的 trait。
Trait 实现必须定义已实现 trait 声明的所有非默认关联条目,可以重新定义已实现 trait 定义的默认关联条目,并且不能定义任何其他条目。
关联条目的路径是 <
后跟实现类型的路径,后跟 as
,后跟 trait 的路径,后跟 >
作为路径组件,后跟关联条目的路径组件。
Unsafe traits 要求 trait 实现以 unsafe
关键字开头。
#![allow(unused)] fn main() { #[derive(Copy, Clone)] struct Point {x: f64, y: f64}; type Surface = i32; struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; trait Shape { fn draw(&self, s: Surface); fn bounding_box(&self) -> BoundingBox; } fn do_draw_circle(s: Surface, c: Circle) { } struct Circle { radius: f64, center: Point, } impl Copy for Circle {} impl Clone for Circle { fn clone(&self) -> Circle { *self } } impl Shape for Circle { fn draw(&self, s: Surface) { do_draw_circle(s, *self); } fn bounding_box(&self) -> BoundingBox { let r = self.radius; BoundingBox { x: self.center.x - r, y: self.center.y - r, width: 2.0 * r, height: 2.0 * r, } } } }
Trait 实现一致性
如果孤儿规则检查失败或存在重叠的实现实例,则 trait 实现被认为是不一致的。
当实现所针对的 trait 存在非空交集,且实现可以使用相同的类型实例化时,两个 trait 实现重叠。
孤儿规则
给定 impl<P1..=Pn> Trait<T1..=Tn> for T0
,一个 impl
只有在至少满足以下条件之一时才有效
Trait
是一个 本地 trait- 全部满足以下条件:
仅限制未覆盖类型参数的出现。
请注意,出于一致性的目的,基本类型是特殊的。Box<T>
中的 T
不被认为是覆盖的,而 Box<LocalType>
被认为是本地的。
泛型实现
实现可以接受泛型参数,这些参数可以在实现的其余部分中使用。实现参数直接写在 impl
关键字之后。
#![allow(unused)] fn main() { trait Seq<T> { fn dummy(&self, _: T) { } } impl<T> Seq<T> for Vec<T> { /* ... */ } impl Seq<bool> for u32 { /* Treat the integer as a sequence of bits */ } }
如果泛型参数至少在以下之一中出现一次,则泛型参数约束实现
类型和 const 参数必须始终约束实现。如果生命周期在关联类型中使用,则生命周期必须约束实现。
约束情况的示例
#![allow(unused)] fn main() { trait Trait{} trait GenericTrait<T> {} trait HasAssocType { type Ty; } struct Struct; struct GenericStruct<T>(T); struct ConstGenericStruct<const N: usize>([(); N]); // T constrains by being an argument to GenericTrait. impl<T> GenericTrait<T> for i32 { /* ... */ } // T constrains by being an argument to GenericStruct impl<T> Trait for GenericStruct<T> { /* ... */ } // Likewise, N constrains by being an argument to ConstGenericStruct impl<const N: usize> Trait for ConstGenericStruct<N> { /* ... */ } // T constrains by being in an associated type in a bound for type `U` which is // itself a generic parameter constraining the trait. impl<T, U> GenericTrait<U> for u32 where U: HasAssocType<Ty = T> { /* ... */ } // Like previous, except the type is `(U, isize)`. `U` appears inside the type // that includes `T`, and is not the type itself. impl<T, U> GenericStruct<U> where (U, isize): HasAssocType<Ty = T> { /* ... */ } }
非约束情况的示例
#![allow(unused)] fn main() { // The rest of these are errors, since they have type or const parameters that // do not constrain. // T does not constrain since it does not appear at all. impl<T> Struct { /* ... */ } // N does not constrain for the same reason. impl<const N: usize> Struct { /* ... */ } // Usage of T inside the implementation does not constrain the impl. impl<T> Struct { fn uses_t(t: &T) { /* ... */ } } // T is used as an associated type in the bounds for U, but U does not constrain. impl<T, U> Struct where U: HasAssocType<Ty = T> { /* ... */ } // T is used in the bounds, but not as an associated type, so it does not constrain. impl<T, U> GenericTrait<U> for u32 where U: GenericTrait<T> {} }
允许的非约束生命周期参数的示例
#![allow(unused)] fn main() { struct Struct; impl<'a> Struct {} }
不允许的非约束生命周期参数的示例
#![allow(unused)] fn main() { struct Struct; trait HasAssocType { type Ty; } impl<'a> HasAssocType for Struct { type Ty = &'a Struct; } }
实现上的属性
实现可以在 impl
关键字之前的外部包含属性,以及在包含关联条目的括号内的内部属性。内部属性必须在任何关联条目之前出现。此处有意义的属性是 cfg
、deprecated
、doc
和 lint 检查属性。