阿里云市场网站建设,门户网站简单模板,wap网站平台,电商平台网站建设喜欢的话别忘了点赞、收藏加关注哦#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵#xff01;(#xff65;ω#xff65;)
题外话#xff1a;trait的概念非常非常非常重要#xff01;#xff01;#xff01;整个第10章全都是Rust的重难点#xff01;#x…喜欢的话别忘了点赞、收藏加关注哦对接下来的教程有兴趣的可以关注专栏。谢谢喵(ω)
题外话trait的概念非常非常非常重要整个第10章全都是Rust的重难点
10.3.1. 什么是trait
trait意为特征、特质。trait用来向Rust编译器描述某种类型具有哪些并且可以与其它类型共享的功能。trait可以以抽象的方式来定义共享的行为。
与trait相关的还有trait bounds(约束)的概念它可以将泛型类型参数指定为实现了特定行为的类型。换句话说就是要求泛型的类型参数实现了某些triat。
Rust里的trait与其他语言的接口(interface)有点类似但还是有区别的。
10.3.2. 定义一个trait
类型的行为由该类型本身可调用的方法来组成。有时候在不同的类型上都具有相同的方法这时候就称这些类型共享了相同的行为。trait提供了一种方式可以把一些方法放到一起从而定义实现某种目的所必需的一种行为。
定义trait使用关键字trait在trait的定义内只有方法签名没有具体实现trait可以有多个方法每个方法占一行以;结尾实现该trait的类型必须提供具体的方法实现也就是必须有方法体
看个例子
pub trait Summary {fn summarize(self) - String;
}trait前面加上pub代表公共的这个trait的名字是Summary里面有一个方法的签名叫summerize除了self之外没有其他参数返回类型是String然后加一个;就结束了这个签名它没有方法体也就是没有具体的实现。当然一个trait下可以有很多个方法签名
pub trait Summary {fn summarize(self) - String;fn summarize1(self) - String;fn summarize2(self) - String;//......
}10.3.3. 在类型上实现trait
在类型上实现trait与为类型实现方法很类似但是也有不同之处。
为类型实现方法的写法是impl关键字后面跟着类型就可以了:
impl Yyyy {....}而在类型上实现trait的写法是:
impl Xxxx for Yyyy {....}Xxxx指的是trait的名Yyyy指的是类型的名在花括号内需要对trait里的方法签名写下具体的实现
看个例子(lib.rs)
pub trait Summary {fn summarize(self) - String;
}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)}
}结构体NewsArticle表示新闻文章它有4个字段:headline标题、location地点、author作者、content内容结构体Tweet表示推特现在是X了推文它有四个字段:username用户名、content内容、reply是否有回复、retweet是否是转发
这两个结构体类型肯定不同里面的字段大部分也不同。但是它们都可以有一个同样的行为——提取摘要Summary所以就分别在这两个类型上实现Summary这个trait。
impl Summary for NewsArticle {fn summarize(self) - String {format!({}, by {} ({}), self.headline, self.author, self.location)}
}这一段是在NewsArticle实现trait因为在定义trait时写了summarize的方法签名所以在这里就得写具体的实现使用format!这个宏将self.headline、self.author和self.location组成一个字符串返回。
impl Summary for Tweet {fn summarize(self) - String {format!({}: {}, self.username, self.content)}
}这一段是在Tweet上实现trait也是一样的写summarize的具体实现使用format!这个宏将self.username和self.content组成一个字符串返回。
然后来到main.rs看它们实例的调用
use RustStudy::{Summary, Tweet};fn main() {let tweet Tweet {username: String::from(horse_ebooks),content: String::from(of course, as you probably already know, people,),reply: false,retweet: false,};println!(1 new tweet: {}, tweet.summarize());
}记住在main函数里使用之前要先引入作用域写法是:
use 你的package名::...::你需要的模块你的package名就是Cargo.toml里的项目名把它复制下来即可
这里引入Summary是因为使用了在Summary这个trait下的summarize方法引入Tweet是因为使用了Tweet这个结构体。
看一下输出
1 new tweet: horse_ebooks: of course, as you probably already know, people10.3.4. trait的约束
想要在某个类型上实现某个trait的前提条件是
这个类型比如说Tweet类型或这个trait让Vector实现本地的Summary是在本地crate里定义的无法为外部类型实现外部trait。比如说在本地库里为标准库的Vector实现标准库的Display trait。 这个限制是程序属性的一部分也就是一致性。更具体的说是孤儿原则之所以这么命名是因为它的父类型并没有定义在当前库中。这个规则确保了其他人的代码不能随意破坏你的代码反之亦然。如果没有这个规则两个crate可以为同一个类型实现同一个traitRust就不知道应该使用哪个实现。
10.3.5. 默认实现
有些时候为trait中的某些或者是所有方法提供默认行为是非常有用的它可以使我们无需为每一个类型的实现都提供自定义的行为。我们可以针对某些特定的类型实现trait里的方法。
当我们为某些类型实现trait时我们可以选择保留或是重载每个方法的默认实现。
之前的写法是:
pub trait Summary {fn summarize(self) - String;
}之前的写法只写了方法的签名没有写实现而其实可以给它写一个默认的实现
默认实现
pub trait Summary {fn summarize(self) - String {String::from((Read more...))}
}这里的默认实现就是返回一个字符串(Read more…)
由于这个方法在trait里面已经有一个默认实现了所以在具体的类型上就可以直接采用这个默认实现而不进行自己的实现。
以NewsArticle为例原本它有自己的实现(或者叫做默认实现的重写的实现)
impl Summary for NewsArticle {fn summarize(self) - String {format!({}, by {} ({}), self.headline, self.author, self.location)}
}只要删掉这个具体实现就可以让NewsArticle用默认实现
impl Summary for NewsArticle {}还有一点需要知道默认实现的方法可以调用trait中其它的方法即使这些方法没有默认实现
pub trait Summary {fn summerize_author(self) - Stringfn summarize(self) - String {String::from((Read more from {}...), self.summerize_author())}
}在summarize的默认实现里调用了summerize_author即使它只是一个签名没有具体实现。但如果想要在类型上实现summerize的话就需要先写summerize_author的实现
impl Summary for NewsArticle {fn summerize_author(self) - String {format!({}, self.author)}
}PS由于NewsArticle的summarize使用的是默认实现所以就不需要在这里写summerize的默认实现了
这个写法有一点注意无法从方法的重写实现里面调用默认的实现