RUST学习-trait

rust的trait很想是java的interface

如何定义、实现一个trait

通过关键字pub trait XXX{},trait里定义的方法如果没有默认实现,可以没有方法体,那么所有实现该trait的strut的必须实现该方法,如果提供默认方法。

1
2
3
4
5
6
7
8
9
10
11
//定义trait 并且定义了trait的函数,给出了默认实现
pub trait Summary {
//默认实现类似于Java的Abstact模板类
fn sumarize_auther(&self) -> String {
return "unknown".to_string();
}

fn sumarize(&self) -> String {
return format!("(Read mor form {}...)", &self.sumarize_auther());
}
}

实现该trait其中NewsArticle和Tweet都实现了Summary这个trait

  • 需要注意的是如果要实现trait,必须满足trait或者类型是在当前pakcage下定义的【为了安全防止你的代码别别人破坏或者别人破坏你的代码】
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
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub auther: String,
pub content: String,
}

//实现trait
impl Summary for NewsArticle {
fn sumarize(&self) -> String {
return format!("{},by {} ({})", self.headline, self.auther, self.location);
}
}

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

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

main函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
fn main() {
let news_article = &NewsArticle {
headline: String::from("头条"),
location: String::from("北京"),
auther: String::from("ericliu"),
content: String::from("学习RUST的trait"),
};

println!("新闻摘要:{}", news_article.sumarize());
println!("新闻 break_info:{}", news_article.break_info());

let tweet = &Tweet {
username: "ericliu".to_string(),
content: String::from("学习RUST的trait"),
reply: false,
retweet: false,
};

println!("推文摘要:{}", tweet.sumarize());
println!("推文 break_info:{}", tweet.break_info());
}

trait bound

我们在定义方法如果用到泛型的时候可以通过trait bound的概念对泛型进行一些定义,类似java中的这种用法,看例子

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
fn main() {
println!("get_largest {}",get_largest(vec![1,-1,100,-100,200]));
println!("get_largest2 {}",get_largest2(vec!["hello".to_string(),"world".to_string(),"a".to_string()]));
}

//只有实现了PartialOrd的泛型所指的类型T
//T实现了Copy的Trait,一般指对象声明在Stack上否则let mut res = v[0];会报错Cannet move
fn get_largest<T:PartialOrd+Copy>(v: Vec<T>) -> T {
let mut res = v[0];
for &item in v.iter() {
if res < item {
res = item;
}
}
return res;
}

//只有实现了PartialOrd的泛型所指的类型T
//T实现了Copy的Trait,一般指对象声明在Stack上否则let mut res = v[0];会报错Cannet move
fn get_largest2<T:PartialOrd+Clone>(v: Vec<T>) -> T {
let mut res = v[0].clone();
for item in v.iter() {
if res < item.clone() {
res = item.clone();
}
}
return res;
}

trait可以对泛型的实现进行限制

该场景主要用于加强某些trait的行为,比如说让所有实现了traitA的类型具有B的功能,具体实现方法见下面,典型的例子是rust标准库中实现了Display的函数都实现了ToString这个trait

1
2
3
4
5
6
7
8
9
10
pub trait BreakNews {
fn break_info(&self) -> String;
}

//通过trait限制泛型的类型:给所有实现Summary的泛型实现break_info
impl<T: Summary> BreakNews for T {
fn break_info(&self) -> String {
return format!("break_info :{}", self.sumarize());
}
}