覆盖默认实现
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 32 课,共 61 课。
默认实现很方便,但有时类型需要不同于标准行为的行为。这种情况下,你可以在 impl 块中提供自己的实现,来重写默认实现。
只需定义具有相同签名的方法,并加入你自定义的逻辑:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
虽然 Greet 提供了默认的 greet 方法,但 Robot 用自己的版本完全替换了它。当你对 Robot 调用 greet() 时,Rust 会使用自定义实现:
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // 哔哔啵啵。42 号机器人已上线。
这样更灵活:适用默认行为的类型无需编写任何内容,而需要专门行为的类型可以只重写它们需要的方法。这个 trait 仍能保证每个实现它的类型都拥有该方法。
挑战
简单让我们构建一个通知系统,让不同类型的警报可以自定义消息!你将创建一个带默认实现的 trait,然后让一种类型使用默认实现,另一种类型通过自定义行为覆盖它。
你将把代码分到三个文件中:
notifiable.rs:定义一个公有的Notifiabletrait,其中包含一个notify(&self) -> String方法,该方法有一个默认实现,会返回"Alert: Something happened!"。alerts.rs:创建两个以不同方式实现该 trait 的公有结构体:GenericAlert:一个使用默认通知的单元结构体(空的 impl 块)UrgentAlert:一个包含公有message字段(String)的结构体,它会覆盖默认实现,返回"URGENT: {message}",其中{message}是它存储的消息
main.rs:整合各个模块并演示这两种行为。使用提供的输入创建一个GenericAlert和一个UrgentAlert,然后打印它们的通知。
这里的关键在于,GenericAlert 会免费获得默认行为,而 UrgentAlert 则通过在自己的 impl 块中定义该方法,提供专门的实现。
你的输出应符合以下格式:
Alert: Something happened!
URGENT: {message}例如,输入 Server is down! 时:
Alert: Something happened!
URGENT: Server is down!你将收到一个输入:紧急警报的消息。
亲手试试
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// 读取紧急警报消息的输入
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: 创建一个 GenericAlert 实例
// TODO: 用输入的消息创建一个 UrgentAlert 实例
// TODO: 打印 GenericAlert 的通知
// TODO: 打印 UrgentAlert 的通知
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器