什么是trait?
Trait其实就是告诉编译器:
- 某种类型具有哪些行为,并且这些行为其他的类型也可以拥有(类似于接口interface)
- trait是一个公共行为的签名集合,也就是只声明有哪种行为,不做具体实现
- 利用关键字trait就可以声明一个Trait
```rust
pub trait Summary {
// trait实现的只是一个签名的集合,并不会有具体的实现
fn summarize(&self) -> String
}
pub struct NewsArticle { pub headline: String, pub location: String, pub author: String, pub content: String, }
pub struct Tweet { pub username: String, pub content: String, pub reply: bool, pub retweet: bool, }
// 为结构体实现trait,这里就是trait中签名的具体实现 impl Summary for NewsArticle { fn summarize(&self) -> String { format!(“{},作者{}({})”, self.headline, self.author, self.location) } }
impl Summary for Tweet { fn summarize(&self) -> String { format!(“{},用户名:{}”, self.content, self.username) }
}
从上面的例子可以看出:- Summary作为一个trait,定义了一个行为summarize- 这个行为结构体NesArticle和Tweet都可以拥有<a name="daYqU"></a>## 默认行为- 默认行为:我们在定义trait的签名时,是可以给一个默认实现的- 默认实现中可以调用当前trait中的方法,即使这个方法是没有默认实现的- 默认行为可以通过在具体类型中实现trait时给重写掉基于上面的例子我们来看下```rustpub trait Summary {fn get_user(&self) -> String;// 这里就是默认实现,并且调用了自身的get_user这个方法,并且这个方法没有默认实现fn summarize(&self) -> String {format!("这是默认实现的trait,详情查看{}", self.get_user())}}pub struct NewsArticle {pub headline: String,pub location: String,pub author: String,pub content: String,}pub struct Tweet {pub username: String,pub content: String,pub reply: bool,pub retweet: bool,}// 为结构体实现trait,这里就是trait中签名的具体实现impl Summary for NewsArticle {fn summarize(&self) -> String {format!("{},作者{}({})", self.headline, self.author, self.location)}fn get_user(&self) -> String {format!("{}", self.author)}}impl Summary for Tweet {// fn summarize(&self) -> String {// format!("{},用户名:{}", self.content, self.username)// }fn get_user(&self) -> String {format!("{}", self.username)}}let tweet = Tweet {username: String::from("horse_ebooks"),content: String::from("of course, as you probably already know, people"),reply: false,retweet: false,};// 调用该trait的方法println!("1 new tweet: {}", tweet.summarize());
trait作为参数
trait作为参数的意思就是:
这个参数是实现了某个trait的这样一个结构
trait作为参数有两种方式:
- impl XXX
- Trait bound
我们基于上面的例子继续来解读一下:
我们需要实现一个notify方法,这个方法的参数item需要是实现了Summary这个trait的结构
impl trait
// 第一种方法pub fn notify(item: impl Summary) {print!("爆炸新闻来袭!{}", item.summarize());}
Trait bound
- Trait bounds:可以将泛型的类型绑定为某些trait
// 将类型T绑定为实现了 Summary 这个trait的这样一个类型 pub fn notify<T: Summary>(item: T) { print!("爆炸新闻来袭!{}", item.summarize()); }利用+来绑定多来trait
如果现在的需求是一个类型是Summary和Copy这两个trait实现的类型呢?
pub fn notify<T: Summary + Copy>(item: T) {
print!("爆炸新闻来袭!{}", item.summarize());
}
当然这样如果是trait过多的话,就会造成函数的签名看起来很繁琐,所以rust提供了一个where给我们使用。
使用where简化多个绑定
where写在返回值类型的后面即可
pub fn notify<T, U>(item: T, item2: U)
where
T: Summary + Copy,
U: xxxx + yyyy,
{
print!("爆炸新闻来袭!{}", item.summarize());
}
总结

