Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English Original

10. Trait (特征) 🟢

Trait 定义了特定类型所拥有并可以与其他类型共享的功能。我们可以使用 Trait 以抽象的方式定义共同的行为。

1. 定义一个 Trait

Trait 的定义是将方法签名组合在一起,以定义完成某种目的所需的一系列行为。

#![allow(unused)]
fn main() {
pub trait Summary {
    fn summarize(&self) -> String;
}
}

2. 为类型实现 Trait

每个实现了该 Trait 的类型都必须为方法的正文提供其自定义行为。

#![allow(unused)]
fn main() {
pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
}
}

3. 默认实现

有时为 Trait 中的部分或全部方法提供默认行为会很有用。

#![allow(unused)]
fn main() {
pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(阅读更多...)")
    }
}
}

4. Trait 作为参数

我们可以使用 Trait 来定义那些接受多种不同类型的函数。

#![allow(unused)]
fn main() {
pub fn notify(item: &impl Summary) {
    println!("突发新闻!{}", item.summarize());
}
}

5. 返回实现了 Trait 的类型

我们还可以在返回值位置使用 impl Trait 语法,以返回实现了该 Trait 的某种类型的值。

#![allow(unused)]
fn main() {
fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("当然,正如你可能已经知道的,人们情有独钟"),
        reply: false,
        retweet: false,
    }
}
}

对 C/C++ 开发者的总结

  • 在 C++ 中:你使用带有虚函数的抽象基类来实现多态。
  • 在 Rust 中:你使用 Trait。不存在类继承。Trait 允许你在类型定义之后再为其添加行为(只要 Trait 或类型中有一个是属于当前 Crate 的)。这比 C++ 接口要灵活得多。