Menu
CoddyTech

默认实现

本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 31 课,共 61 课。

到目前为止,我们定义的每个 trait 方法都只有签名:这是一个没有函数体的要求。但如果大多数实现某个 trait 的类型都会使用相同的逻辑呢?Rust 允许你直接在 trait 定义中提供默认实现。

你不再用分号结束方法签名,而是添加方法体:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

现在,任何实现了 Greet 的类型都会自动获得这个方法,无需在 impl 块中编写任何代码:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // 你好!

空的 impl Greet for Guest {} 是有效的,因为该特征已经提供了相关行为。这个结构体只需“选择加入”该特征,就能免费获得默认方法。

当你想定义适用于大多数情况的共享行为时,这种模式很有用。需要不同实现的类型可以覆盖默认行为(你将在下一课中学习),而适用标准行为的类型则不必重复编写。

challenge icon

挑战

简单

让我们通过构建一个通知系统,来探索默认实现的强大之处!你将创建一个提供开箱即用的标准行为的特征,这样类型就能直接采用这些行为,无需编写重复的代码。

你将把代码分放在三个文件中:

  • notifiable.rs:定义一个公开的 Notifiable 特征,其中包含一个具有默认实现的 notify(&self) -> String 方法。默认实现应返回 "You have a new notification!"。任何实现了此特征的类型都会自动获得这种行为,无需在其 impl 块中编写任何内容。
  • alerts.rs:创建两个实现此特征的简单公开单元结构体:
    • EmailAlert:通过空 impl 块实现 Notifiable(使用默认实现)
    • SystemAlert:同样通过空 impl 块实现 Notifiable(使用默认实现)
    这两个结构体都会自动获得默认通知消息,无需你编写任何方法体!
  • main.rs:整合各个模块,并演示这两种警报类型如何共享相同的默认行为。创建这两个结构体的实例,并调用它们的 notify 方法。

在主文件中,创建一个 EmailAlert 和一个 SystemAlert,然后将它们的通知分别打印在单独的行上。

你的输出应为:

You have a new notification!
You have a new notification!

注意,这两种类型会生成完全相同的输出:这就是默认实现的妙处!这两个结构体都不需要为 notify 方法编写任何代码,却都拥有了完整可用的通知行为。在下一课中,你将学习如何在类型需要自定义行为时覆盖这些默认实现。

亲手试试

mod notifiable;
mod alerts;

use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};

fn main() {
    // TODO:创建一个 EmailAlert 实例
    
    // TODO:创建一个 SystemAlert 实例
    
    // TODO:打印来自 EmailAlert 的通知
    
    // TODO:打印来自 SystemAlert 的通知
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Rust 在线编译器