10.1 泛型
rust
的泛型函数和泛型结构和其他语言比较像。
struct Point<T>{
x: T,
y: T,
}
需要注意的是,rust
可以为泛型实现特化函数,但泛型函数和特化函数不能同时存在。如下代码实现的逻辑在其他语言中是OK的,在rust
中无法编译通过。
imp<T> Point<T> {
fn distance(&self) -> T {
sqrt(self.x * self.x + self.y * self.y)
}
}
imp Point<i32> {
fn distance(&self) -> i32{
sqrt(self.x * self.x + self.y * self.y)
}
}
第2个需要注意的是,在泛型中,其实什么也做不了。在rust
中默认泛型不实现任务功能,数值运算、输出、都不可以。
rust
必须明确指明泛型参数具有哪些能力。
10.2 特性
rusrt
中特性的traits
很有意思,类似于接口,但又有区别。
pub trait Summary {
fn Summerize(&self) -> String;
}
以上代码就定义了一个特性,然后每个结构可以实现这个特性:
pub struct Article {
name: String,
content: String,
}
impl Summary for Article {
fn Summerize(&self) -> String{
...;
}
}
特性可以有默认实现:
pub trait Summary{
fn summerize(&self) -> String{
"Summary".to_string()
}
}
定义特性的实现时,必须要求特性定义在本地或者结构定义在本地,也就是说,不允许为外部结构定义外部特性,从而避免重写别人的代码。
特性和接口一样,可以作为函数参数使用:
// 简单写法,属于语法糖
fn Test(v: &impl Summary) {
}
// 等同于
fn Test<T: Summary>(v: &T){
}
// 也可以写为where,主要用于参数比较多的情况下
fn Test<T>(v: &T)
where T: Summary
{
}
特性作为参数使用时,可以要求模板参数实现多个特性,用+
相连。
fn Test<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32{
}
也可以要求返回类似必须实现某个特性。
fn Test() -> impl Summary{
}
需要注意的是,返回类似为特性时,返回的类型必须相同,不能返回两个不相同的类型。
利用特性,我们可以实现类似于 c#
的interface
。
10.3 引用的生命周期
基于rust
的生命周期严格管控,看代码:
fn longer(l: &str, r: &str) -> &str {
if l.len() < r.len() {
r
} else {
l
}
}
fn left(l: &str, r: &str) -> &str{
l
}
所以返回值是 l
还是r
?第一个不清楚,第二个肯定返回l
。。返回值的生命周期是跟l
还是跟r
?还是都跟?
所以rust
定义了生命周期标记'
',用于标记生命周期。如上可以标记为:
fn longer<'a>(l: &'a str, r: &'a str) -> &'a str {
if l.len() < r.len() {
r
} else {
l
}
}
fn left<'a, 'b>(l: &'a str, r: &'b str) -> &'a str{
l
}
如此一目了解,logger
函数返回值生命周期跟两个参数,left
函数生命周期跟参数l
。看起来类似于泛型,这也是泛型的一种。
然而如果每个函数都这么写也太麻烦了,所以rust
发展出了省略的方法,编译器会自动帮我们加上生命周期标记:
- 为函数的每个传入的类型添加引用标记;需要注意的是,对复杂类型可能需要添加两个标记。
- 如果函数只有一个传入标记,那它就是传出引用的标记。
- 如果第一个参数是
&self
或者&mut self
,传出标记使用self
的标记。
需要注意的是对复杂结构如
struct Sample<'a'>{
part: &'a str,
}
// 函数
fn TestSample(s: &Sample)-> &str{
s.part
}
// 自动添加生命周期符号后
fn TestSample<'a, 'b>(s: &'a Sample<'b>) -> &'b str{
s.part
}
对上面代码的 TestSample
函数,编译器会添加如第2个实现这样的参数标记,因为有两个参数标记,编译器不知道要给传出标记使用哪个标记,此函数会编译失败,必须明确指明。
- 打赏
- 分享
- 微信
- 支付宝