Rust 语言学习之旅(5)


泛型函数
Rust中的泛型与 Trait 是相辅相成的。 当我们描述一个参数化类型 T 时,我们可以通过列出参数必须实现的 Trait 来限制哪些类型可以作为参数使用。

在以下例子中,类型 T 必须实现 Foo 这个 Trait:

fn my_function<T>(foo: T)
where
    T:Foo
{
    ...
}

通过使用泛型,我们在编译时创建静态类型的函数,这些函数有已知的类型和大小,允许我们对其执行静态调度,并存储为有已知大小的值。

struct SeaCreature {
    pub name: String,
    noise: String,
}

impl SeaCreature {
    pub fn get_sound(&self) -> &str {
        &self.noise
    }
}

trait NoiseMaker {
    fn make_noise(&self);
}

impl NoiseMaker for SeaCreature {
    fn make_noise(&self) {
        println!("{}", &self.get_sound());
    }
}

fn generic_make_noise<T>(creature: &T)
where
    T: NoiseMaker,
{
   
// 我们在编译期就已经知道其真实类型
    creature.make_noise();
}

fn main() {
    let creature = SeaCreature {
        name: String::from(
"Ferris"),
        noise: String::from(
"咕噜"),
    };
    generic_make_noise(&creature);
}

泛型函数简写
Rust 为由 Trait 限制的泛型函数提供了简写形式:

fn my_function(foo: impl Foo) {
    ...
}

这段代码等价于:

fn my_function<T>(foo: T)
where
    T:Foo
{
    ...
}

复杂代码:

struct SeaCreature {
    pub name: String,
    noise: String,
}

impl SeaCreature {
    pub fn get_sound(&self) -> &str {
        &self.noise
    }
}

trait NoiseMaker {
    fn make_noise(&self);
}

impl NoiseMaker for SeaCreature {
    fn make_noise(&self) {
        println!("{}", &self.get_sound());
    }
}

fn generic_make_noise(creature: &impl NoiseMaker)
{
   
// 我们在编译期就已经知道其真实类型
    creature.make_noise();
}

fn main() {
    let creature = SeaCreature {
        name: String::from(
"Ferris"),
        noise: String::from(
"咕噜"),
    };
    generic_make_noise(&creature);
}

Box
Box 是一个允许我们将数据从栈上移到堆上的数据结构。
Box 是一个被称为智能指针的结构,它持有指向我们在堆上的数据的指针。
由于 Box 是一个已知大小的结构体(因为它只是持有一个指针), 因此它经常被用在一个必须知道其字段大小的结构体中存储对某个目标的引用。
Box 非常常见,它几乎可以被用在任何地方:
Box::new(Foo { ... })

代码:

struct SeaCreature {
    pub name: String,
    noise: String,
}

impl SeaCreature {
    pub fn get_sound(&self) -> &str {
        &self.noise
    }
}

trait NoiseMaker {
    fn make_noise(&self);
}

impl NoiseMaker for SeaCreature {
    fn make_noise(&self) {
        println!("{}", &self.get_sound());
    }
}

struct Ocean {
    animals: Vec<Box<dyn NoiseMaker>>,
}

fn main() {
    let ferris = SeaCreature {
        name: String::from(
"Ferris"),
        noise: String::from(
"咕噜"),
    };
    let sarah = SeaCreature {
        name: String::from(
"Sarah"),
        noise: String::from(
"哧溜"),
    };
    let ocean = Ocean {
        animals: vec![Box::new(ferris), Box::new(sarah)],
    };
    for a in ocean.animals.iter() {
        a.make_noise();
    }
}


泛型结构体
泛型结构体也可以通过 Trait 来约束其参数化类型:

struct MyStruct<T>
where
    T: MyTrait
{
    foo: T
    ...
}

泛型结构体在它的实现块中有其参数化的类型:

impl<T> MyStruct<T> {
    ...
}