实现
语法
Implementation :
InherentImpl | TraitImplInherentImpl :
implGenericParams? Type WhereClause?{
InnerAttribute*
AssociatedItem*
}TraitImpl :
unsafe?implGenericParams?!? TypePathforType
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 trait 要求 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只有在以下至少一个条件为真时才有效:
只有未覆盖类型参数的出现受到限制。
注意,为了实现一致性,基础类型构造器是特殊的。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 检查属性。