实现特征
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 30 课,共 61 课。
现在你已经知道如何定义 trait,接下来看看如何让结构体满足这份契约。实现 trait 可以将抽象要求与具体行为联系起来。
语法使用 impl TraitName for StructName:
trait Speak {
fn speak(&self) -> String;
}
struct Dog {
name: String,
}
impl Speak for Dog {
fn speak(&self) -> String {
format!("{} says: Woof!", self.name)
}
}
impl Speak for Dog 代码块告诉 Rust,Dog 正在实现 Speak trait。在其中,你需要提供实际的方法体。这里定义了狗如何说话。
当多个类型实现同一个特征时,特征的强大之处就显而易见了:
struct Cat {
name: String,
}
impl Speak for Cat {
fn speak(&self) -> String {
format!("{} says: Meow!", self.name)
}
}
现在,Dog 和 Cat 都具有 Speak 能力,但各自提供了独特的实现。你可以对任一类型调用 .speak():
let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };
println!("{}", dog.speak()); // Rex 说:Woof!
println!("{}", cat.speak()); // Whiskers 说:Meow!
这是 Rust 中多态的基础:不同的类型,相同的接口,各自独特的行为。
挑战
简单让我们通过为不同类型实现 trait,让它们发挥作用!你将创建一个 Describable trait,并为两个不同的结构体实现它,每个结构体都提供独特的描述。
你将在三个文件中组织代码:
describable.rs:定义一个公开的Describabletrait,其中包含一个方法describe(&self) -> String。items.rs:创建两个实现该 trait 的公开结构体:Book,包含一个公开的title字段(String)Movie,包含一个公开的name字段(String)
Describable,并采用各自独特的描述格式。main.rs:将各个模块组合起来,创建这两个结构体的实例,并调用它们的describe方法,展示同一个 trait 如何为不同类型生成不同的输出。
你的 Book 应将自身描述为 Book: {title},而你的 Movie 应将自身描述为 Film: {name}。注意,每种类型都遵循相同的约定,但行为各不相同!
在主文件中,使用提供的两个输入创建一本书和一部电影,然后分别在单独的行中打印它们的描述。
你的输出应遵循以下格式:
Book: {title}
Film: {name}例如,输入为 1984 和 Inception 时:
Book: 1984
Film: Inception你将收到两个输入:书名和电影名称。
亲手试试
mod describable;
mod items;
use describable::Describable;
use items::{Book, Movie};
fn main() {
// 读取输入
let mut title = String::new();
std::io::stdin().read_line(&mut title).expect("Failed to read line");
let title = title.trim().to_string();
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
// TODO: 用 title 创建一个 Book 实例
// TODO: 用 name 创建一个 Movie 实例
// TODO: 打印书籍的描述
// TODO: 打印电影的描述
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器