实现
语法
实现 :
固有实现 | 特征实现固有实现 :
impl
泛型参数? 类型 Where子句?{
内部属性*
关联项*
}
特征实现 :
unsafe
?impl
泛型参数?!
? 类型路径for
类型
Where子句?
{
内部属性*
关联项*
}
实现 是一个将项目与 实现类型 关联起来的项目。实现使用关键字 impl
定义,并包含属于正在实现的类型的实例或静态类型的函数。
有两种类型的实现
- 固有实现
- 特征 实现
固有实现
固有实现定义为 impl
关键字、泛型类型声明、指向名义类型的路径、where 子句和一组括号内的可关联项目的序列。
名义类型称为 实现类型,可关联项目是实现类型的 关联项目。
固有实现将包含的项目与实现类型相关联。固有实现可以包含 关联函数(包括 方法)和 关联常量。它们不能包含关联类型别名。
关联项目的 路径 是指向实现类型的任何路径,后跟关联项目的标识符作为最终路径组件。
一个类型也可以有多个固有实现。实现类型必须与原始类型定义在同一个包中定义。
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(); }
特征实现
特征实现 的定义类似于固有实现,只是可选的泛型类型声明后跟一个 特征,然后是关键字 for
,然后是指向名义类型的路径。
该特征称为 已实现特征。实现类型实现了已实现特征。
特征实现必须定义已实现特征声明的所有非默认关联项目,可以重新定义已实现特征定义的默认关联项目,并且不能定义任何其他项目。
关联项目的路径是 <
后跟指向实现类型的路径,后跟 as
,后跟指向特征的路径,后跟 >
作为路径组件,后跟关联项目的路径组件。
不安全特征 要求特征实现以 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, } } } }
特征实现一致性
如果特征实现无法通过孤儿规则检查或存在重叠的实现实例,则该实现被认为是不连贯的。
当满足以下条件时,两个特征实现会发生重叠:实现所针对的特征存在非空交集,并且可以使用相同的类型实例化这些实现。
孤儿规则
给定 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 */ } }
如果泛型参数至少在以下一项中出现一次,则该参数会_约束_实现:
类型和常量参数必须始终约束实现。如果生命周期在关联类型中使用,则生命周期必须约束实现。
约束情况示例
#![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 检查属性。