673 字
约 2 分钟
0
特征

特征

在为 list 命令实现 set_titleset_content 方法时, 我们使用了 Into<String> 进行类型约束。 但 Into<T> 并非是类型, 它是一个特征, 是 Rust 用于定义行为约定的一种机制。可以为类型定义统一的能力规范。

我们可以将 Rust 中的特征看作是其他语言中的接口。

Rust 内置了许多特征。例如 Into<T> 表示可以将类型转换为 TFrom<T> 表示可以从 T 构造出某个类型。 CopyClone 可以表示一个类型是否可以被复制等等。

在最开始我们编写程序时就遇到过一个涉及特征的错误。 String 类型没有实现 Copy 特征, 因此无法直接将参数赋值。

6 |   let title = args[1];
  |               ^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait

声明特征

特征的声明使用 trait 关键字。

trait PrintName {
  fn PrintName(&self) -> String;
}

与枚举一样, 特征只要使用了 pub 修饰, 那么它的方法就全部可供外部访问。

实现特征

特征的实现依赖于类型。在原先的为类型实现方法的基础上增加实现的特征名称和 for 关键字。

trait PrintName {
  fn PrintName(&self) -> String;
}

impl PrintName for TodoItem {
  fn PrintName(&self) -> String {
    "TodoItem".to_string()
  }
}

倘若需要为类型 A 实现特征 B, 那么两者必须有一个是在当前作用域中定义的。否则将无效。 例如想为 String 实现 Copy 特征, 但两者都定义在标准库中而不在当前作用域, 因此无法实现。

这个规则被称为孤儿规则, 它确保了他人编写的代码不会破坏我们的代码, 我们也不会莫名其妙破坏他人的代码。

特征约束

前面我们使用到了特征约束, 即 T: Into<String>。它表示 T 必须实现 Into<String> 特征。

特征约束不仅可以约束泛型, 也可以约束特征自身。

trait PrintName: Display {
  fn PrintName(&self) -> String;
}

以上代码为 PrintName 特征的定义, 它要求实现对象必须实现 Display 特征才能实现它。 可以使用 + 号增加更多的约束。例如 trait PrintName: Display + Clone 表示 PrintName 必须实现 DisplayClone 特征才能实现它。

参数约束

特征也可以用来约束参数类型。

trait PrintName: Display {
  fn PrintName(&self) -> String;
}

fn printName(item: &impl PrintName) {
  println!("{}", item.PrintName());
}

// 以上等价于

fn printName<T: PrintName>(item: &T) {
  println!("{}", item.PrintName());
}
特征
http://www.clxhxhhr.top/posts/452/
作者
clxstart
发布于
2026-09-04
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。
文章目录
目录