Lv777

Lv777

github
twitter
jike
playstation
xiaoyuzhou

泛型

泛型定义#

我一直把泛型理解为类型系统中的参数,因为在 TS 中,类型和执行代码存在隔离。泛型定义就好像一个类型中的函数,通过传入参数得到具体的类型。同时,能通过泛型约束参数,返回值或结构体字段之间的关系.

fn get_value<T>(v: T) -> T {
	v
}

enum Result<T, U> {
	Ok(T),
	Err(U)
}

struct List<T> {
	items: Vec<T>,
	current: T
}

impl<T> List<T> {
	fn first(&self) -> T {
		&self.items[0]
	}
}

为结构体定义方法时也可以限定具体的类型实现类似重载的操作

impl List<i32> {
	fn sum(&self) -> i32 {
		let mut result = 0;
		for item in &self.items {
			result += item
		}
		result
	}
}

// 指定 trait
impl<T: Display> List<T> {
	fn sum(&self) -> i32 {}
}

Rust 的泛型代码不会影响性能,编译时会对其进行单态化, 也就是把使用到泛型的代码编译为具体类型的代码,有点像 Vue3 的静态优化.

Trait#

这玩意有点绕啊

Trait 中文特征,跟 TS 对标类似 interface 或者 abstract class. 我理解为用来对泛型进行约定和限制,让某些抽象的泛型具象了一些,还可以拓展类型添加行为.

trait Desc {
	fn read(&self) -> &str;
	fn default() -> &str {
		"default impl"
	}
}

impl<T> Desc for List<T> {
	fn read(&self) -> &str {
		"a list"
	}
}

实现 Trait 受相干性限制,实现方或者被实现方至少有一个在本地作用域才能进行,这条规则可以避免其他人在 crate 以外破坏代码.

抽象之上的抽象实现 blank implementations.

// 为所有实现过 Display 的类型实现 ToString
impl<T: Display> ToString for T {}

定义后就可以进行约束了

fn get_desc(target: &impl Desc) {}

// trait bound
fn print_desc<T: Desc + Display>(target: &T) -> impl Display {}

fn print_default_desc<T>(target: &T) where T: Desc + Display {}

生命周期#

生命周期的存在是为了保证引用有效,避免悬垂引用。因为所有权的限制,被引用的对象不能比引用者存在时间短,我们不可能在函数体内创建一个引用然后返回,否则离开作用域时源数据被销毁,返回的引用将成为悬垂引用。所以如果一个函数返回了引用,则引用一定与参数中的引用有关联。这个关联有时候无法通过代码推断,比如传入两个引用返回了一个引用,这时就需要我们去明确指定生命周期辅助编译器完成推断.

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
	if x.len() > y.len() {
		x
	} else {
		y
	}
}

// 根据逻辑不需要为 y 指定生命周期
fn first<'a>(x: &'a str, y: &str) -> &'a str {
	x
}

struct Person<'a> {
	name: &'a str
}

// 静态生命周期, 有点像 any, 使用前要保证其能存在整个程序运行过程
let s:&'static str = "hello"

省略规则#

Rust 内置了一些可预测的模式减少重复代码,如果在这些规则之后仍存在无法推断的生命周期,就需要我们明确指定.

  1. 每个引用的生命周期必须与至少一个输入引用的生命周期相同。
  2. 如果只有一个输入引用,那么输出引用的生命周期与输入引用的生命周期相同。
  3. 如果有多个输入引用,其中一个是 &self 或 &mut self,那么输出引用的生命周期与该输入引用的生命周期相同。
  4. 如果有多个输入引用,其中一个是 &self,那么输出引用的生命周期与另一个输入引用的生命周期相同。
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。