泛型,trait和生命周期

1 泛型

1.1 函数中的泛型

对于两个内容一致,但接受参数类型不一致的函数,可以一个定义泛型版本的函数从而合并函数:

例1.1:

fn largest_i32(list: &[i32]) -> &i32 {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}

fn largest_char(list: &[char]) -> &char {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}

// 合并之后
fn largest<T>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}

目前例1.1还不能通过编译,因为>的比较不能涵盖所有T类型的值,在trait中会再次提起,目前按下不表。

1.2 结构体中的泛型

同样也可以用 <> 语法来定义结构体,它包含一个或多个泛型参数类型字段。

例1.2:

struct Point<T, U> {
x: T,
y: T,
z: U,
}

fn main() {
let integer = Point { x: 5, y: 10, z: 1.0 };
let float = Point { x: 1.0, y: 4.0, z: 1 };
}

1.3 枚举定义中的泛型

我们已经使用过了Option<T>Result<T, E>枚举类型:

例1.3:

enum Option<T> {
Some(T),
None,
}

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

1.4 方法定义中的泛型

例1.4:

struct Point<T> {
x: T,
y: T,
}

impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}

定义方法时也可以为泛型指定限制(constraint)。例如,可以选择为Point<f32>实例实现方法,而不是为泛型Point实例。

例1.5:

impl Point<i32> {
fn x(&self) -> &i32 {
&self.x
}
}

结构体定义中的泛型类型参数并不总是与结构体方法签名中使用的泛型是同一类型。

例1.6:

struct Point<X1, Y1> {
x: X1,
y: Y1,
}

impl<X1, Y1> Point<X1, Y1> {
fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
Point {
x: self.x,
y: other.y,
}
}
}

fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c' };

let p3 = p1.mixup(p2);

println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}

// p3.x = 5, p3.y = c

1.5 泛型的性能

Rust通过在编译时进行泛型代码的单态化(monomorphization)来保证效率。单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。

例1.7:

let integer = Option_i32::Some(5);
let float = Option_f64::Some(5.0);

// 编译器生成假想名

enum Option_i32 {
Some(i32),
None,
}

enum Option_f64 {
Some(f64),
None,
}

2 trait

trait 定义了某个特定类型拥有可能与其他类型共享的功能。