实现

语法
实现 :
   内部实现 | Trait实现

内部实现 :
   impl 泛型参数组? 类型 Where从句? {
      内部属性*
      关联条目*
   }

Trait实现 :
   unsafe? impl 泛型参数组? !? 类型路径 for 类型
   Where从句?
   {
      内部属性*
      关联条目*
   }

实现 条目将 实现类型 与其中条目相关联。 实现使用关键字 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() {
    // 实现类型的真实路径和 impl 在同一模块。
    color::Color::WHITE;

    // 不同模块中的 Impl 块仍然是通过类型的路径来访问。
    color::Color::red();

    // 也可以将路径重新导出到实现类型。
    Color::red();

    // 无效,因为在 `values` 中没有使用 pub 。
    // values::Color::red();
}

Trait 实现

trait实现 和内部实现类似,只是可选的泛型类型声明后面是 trait ,再跟着 for 关键字,最后是指向具名类型的路径。

该 trait 被称为 实现 trait ,由实现类型实现。

trait 所有非默认关联条目必须实现,可以重新定义其定义的默认关联条目,但无法定义任何其他条目。

与实现类型相关联的关联条目的路径是 <,后跟到实现类型的路径,然后是 as,后跟到 trait 的路径,之后 > 作为路径组件,然后是关联条目的路径组件。

Unsafe traits 指的是需要在 trait 实现中使用 unsafe 关键字的 trait 。

#![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 集合存在非空交集,并且这两个 trait 实现都可以实例化为同一类型。

唯一性规则

规定 impl<P1..=Pn> Trait<T1..=Tn> for T0 只有当以下至少一项为真时, impl 才是有效:

  • Trait局部trait
  • 全部为
    • T0..=Tn 中至少有一个类型必须是 局部类型 。让 Ti 成为第一个这样的类型。
    • T0..Ti (不包括 Ti ) 中不得出现 未覆盖类型 参数 P1..=Pn

仅出现 未覆盖 类型参数是受限制的。需要注意的是,在一致性的目的下, 基本类型 是特殊的。 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 {
    /* 将整数视为比特序列 */
}
}

如果泛型参数至少在一种类型的关联条目中出现,则该泛型参数 约束 了实现:

  • 已实现的 trait ,如果有其一
  • 实现类型
  • 作为一个 关联类型约束 ,该类型包含约束实现的另一个参数

类型和常量参数必须始终约束实现。如果在关联类型中使用生命周期,则生命周期必须约束实现。

约束示例:

#![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 通过作为 GenericTrait 的一个参数来约束。
impl<T> GenericTrait<T> for i32 { /* ... */ }

// T 通过作为 GenericTrait 的一个参数来约束。
impl<T> Trait for GenericStruct<T> { /* ... */ }

// 同样地, N 通过作为 ConstGenericStruct 的一个参数来约束
impl<const N: usize> Trait for ConstGenericStruct<N> { /* ... */ }

// T 通过在类型 `U` 的约束中的关联类型来约束,该类型本身是约束 trait 的一个泛型参数。
impl<T, U> GenericTrait<U> for u32 where U: HasAssocType<Ty = T> { /* ... */ }

// 和前面一样,除了类型是 `(U, isize)` 。 `U` 出现在包括 `T` 的类型里面,而不是类型本身。
impl<T, U> GenericStruct<U> where (U, isize): HasAssocType<Ty = T> { /* ... */ }
}

非约束性的示例:

#![allow(unused)]
fn main() {
// 其余的都是错误,因为它们的类型或常量参数不受约束。

// T没有约束,因为它根本就没有出现。
impl<T> Struct { /* ... */ }

// 由于同样的原因,N并没有受到约束。
impl<const N: usize> Struct { /* ... */ }

// 在实现中使用 T 并不会约束 impl。
impl<T> Struct {
    fn uses_t(t: &T) { /* ... */ }
}

// 在 U 的绑定中, T 用作关联类型,但 U 没有约束。
impl<T, U> Struct where U: HasAssocType<Ty = T> { /* ... */ }

// T 在绑定中使用,但不是作为一个关联类型,所以它不受约束。
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 关键字之前包含外围 属性 ,在包含关联条目的括号内部包含内部 属性 。 内部属性必须在任何关联条目之前。在这里有意义的属性是 cfgdeprecateddoc代码分析