Rust impl Trait和dyn Trait

impl Trait:静态分发
dyn Trait:动态分发

静态分发:在编译期就确定了具体返回类型,函数只能返回一种类型。
动态分发:在运行时才能确定具体返回类型,函数可以返回多种类型。

Trait Object:指向trait的指针,假设Animal是一个triait,那么&Animal和Box都是一种Trait Object。

胖指针:用于指代动态大小类型(DST)的引用和原始指针(切片或特征对象)。胖指针包含一个指针以及一些使DST完成(例如长度)的信息。

返回值为impl Trait时用dyn Trait是没问题的

示例代码:

trait Animal {
    fn get_kind(&self) -> String;

    fn default_impl(&self) {
        println!("default impl");
    }
}

impl dyn Animal {
    fn trait_object() {
        println!("trait object");
    }
}

#[derive(Debug)]
struct Dog {}

impl Animal for Dog {
    fn get_kind(&self) -> String {
        "Dog".to_string()
    }
}

struct Cat {}

impl Animal for Cat {
    fn get_kind(&self) -> String {
        "Cat".to_string()
    }
}

// 静态分发
fn get_animal_static() -> impl Animal {
    let x = 1;
    if x == 1 {
        Dog {}
    } else {
        Dog {}
    }
}

// 动态分发
fn get_animal_dyn() -> Box<dyn Animal> {
    let x = 0;
    if x == 1 {
        Box::new(Dog {})
    } else {
        Box::new(Cat {})
    }
}

fn main() {
    let dog = Dog {};
    dog.default_impl();

    let cat = Cat {};
    cat.default_impl();

    // 只有 trait objects 才能调用
    // dog.trait_object();
    // cat.trait_object();

    <dyn Animal>::trait_object();
    let _ = &<dyn Animal>::trait_object();

    let animal = get_animal_static();
    // Dog
    println!("{}", animal.get_kind());

    let animal = get_animal_dyn();
    // Cat
    println!("{}", animal.get_kind());
}

参考:
胖指针:
https://www.sohu.com/a/475756949_121124378

impl Trait & dyn Trait
https://zhuanlan.zhihu.com/p/23791817
https://zhuanlan.zhihu.com/p/109990547

你可能感兴趣的:(Rust,rust)