今天就来学习记录下Rust中的必掌握知识之 Trait

TraitRust 中的接口,可以为不同的类型提供同一类行为(函数)。

定义一个 Trait

1
2
3
4
5
6
7
8
pub trait Summary {
fn summarize_author(&self) -> String;

// 带有默认实现的函数
fn summarize(&self) -> String {
format!("(Read more from {})", self.summarize_author())
}
}

上面代码定义了一个名字为 SummaryTrait ,并且里面分别声明了一个名为 summarize_author() 的函数和一个函数定义 summarize()

定义两个结构体并且实现 Summary Trait

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//  NewsArticle 结构体
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}

// 对 NewsArticle 实现 Summary
impl Summary for NewsArticle {
fn summarize_author(&self) -> String {
format!("@{}", self.headline)
}
}

// Tweet 结构体
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
// 对 Tweet 实现 Summary Trait
impl Summary for Tweet {
fn summarize_author(&self) -> String {
format!("@{}", self.username)
}
}

Trait 作为参数

Trait 用作函数参数可以实现让该函数接受不同的类型实参,只要该类型实现了 该 Trait 就行。

1
2
3
pub fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}

Trait Bound 语法

1
2
3
pub fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}

多个参数例子:

1
2
3
4
pub fn notify<T: Summary>(item: &T, item2: &T) {
println!("Breaking news! {}", item.summarize());
println!("Breaking news! {}", item2.summarize());
}

多种类型例子:

1
2
3
4
pub fn notify<T: Summary, U: Summary>(item: &T, item2: &U) {
println!("Breaking news! {}", item.summarize());
println!("Breaking news! {}", item2.summarize());
}

Where 语法

1
2
3
4
5
6
pub fn print_summary<T>(item: &T)
where
T: super::Summary,
{
println!("print_summary: {}", item.summarize());
}

让参数实现多个 Trait

1
2
3
4
5
6
pub fn notify1<T>(item: &T)
where
T: super::Summary + Display,
{
println!("notify1: {}", item);
}

方式2

1
2
3
pub fn notify<T:  Summary + Display>(item: &T) {
println!("Breaking news! {}", item.summarize());
}

返回 Trait 类型

求最大数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// 求最大数
fn largest<T>(list: &[T]) -> T
where
T: PartialOrd + Copy,
{
let mut largest = list[0];

for &item in list {
if item > largest {
largest = item;
}
}
largest
}