跳转至

Rust泛型和Trait系统

泛型

泛型可以帮助程序员提高编写程序的通用性和开发效率,在运行的时指定数据类型的机制,一个代码模板可以适配多种常见,Rust中也具备这种特性,在Rust泛型是通过<T>这样的泛型语法来表示任意的数据类型。

下面的代码定义了一个矩形他的widthhight是不确定的类型,所有使用泛型来代替。

1
2
3
4
5
6
// 矩形 泛型
#[derive(Debug)]
struct Rectangle<T> {
    width: T,
    height: T,
}
使用的时候则编译器会根据上下文我们传入的类型进行推断出来具体的类型。

1
2
3
4
5
6
7
8
fn main() {
    let rtl = Rectangle {
        width: 6,
        heigth: 12,
    };

    println!("{:?}", rtl);
}
我们还可以通过泛型为其特定的数据类型编写特有的函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 为rectangle实现i32方法
impl Rectangle<f32> {
    pub fn area(&self) -> f32 {
        self.width * self.height
    }
}

// 实现泛型trait
impl<T> Rectangle<T> {
    pub fn widht(&self) -> &T {
        &self.width
    }
    pub fn height(&self) -> &T {
        &self.height
    }
}

特性trait

trait类似于其他语言里面的接口,可以把一些类型共有的函数抽象成一个trait,然后去实现特定的trait即可。

下面第一个Geometry的特性里面有一个area纯虚函数,然后我们去实现它。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 接口特性
trait Geometry {
    fn area(&self) -> i32;
}

// 为i32类型的实现求面积特性
impl Geometry for Rectangle<i32> {
    fn area(&self) -> i32 {
        self.width * self.height
    }
}

// 为rectangle实现i32方法
impl Rectangle<f32> {
    pub fn area(&self) -> f32 {
        self.width * self.height
    }
}
然后我们通过一个闭包函数来测试是否正确。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
fn main() {
    let rtl = Rectangle {
        width: 6,
        height: 12,
    };

    // method `area` not found for this
    println!("area = {}", rtl.area());
    println!("widht = {}", rtl.widht());
    println!("hight = {}", rtl.height());
    println!("{:?}", rtl);

    let area_func = |g: &dyn Geometry| println!("area_func = {}", g.area());

    area_func(&rtl);
}

下面是一个综合例子,一个计算机实现了USB协议!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
struct Computer {
    brand: String,
}

trait USB2 {
    fn usb_2(&self);
}

trait USB3 {
    fn usb_3(&self);
}

impl USB2 for Computer {
    fn usb_2(&self) {
        println!("{} impl usb2.0 ", &self.brand)
    }
}

impl USB3 for Computer {
    fn usb_3(&self) {
        println!("{} impl usb3.0 ", &self.brand)
    }
}

// usb(pc:impl USB3+USB2)
fn usb<T>(pc: T)
where
    T: USB3 + USB2,
{
    pc.usb_2();
    pc.usb_3();
}

fn main() {
    usb(Computer {
        brand: "Dell".to_string(),
    })
}

代码例子