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发展出了省略的方法,编译器会自动帮我们加上生命周期标记:

  1. 为函数的每个传入的类型添加引用标记;需要注意的是,对复杂类型可能需要添加两个标记。
  2. 如果函数只有一个传入标记,那它就是传出引用的标记。
  3. 如果第一个参数是 &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个实现这样的参数标记,因为有两个参数标记,编译器不知道要给传出标记使用哪个标记,此函数会编译失败,必须明确指明。

  • 打赏
  • 分享
分享到...
请选择打赏方式
  • 微信
  • 支付宝

By yhl

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注