MST

星途 面试题库

面试题:Rust 中动态分发与 trait 对象的关系

请解释在 Rust 中动态分发是如何通过 trait 对象来实现运行时多态性的。举例说明在实际代码中,如何定义 trait、实现 trait,以及创建和使用 trait 对象来达成动态分发。
49.2万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 动态分发与运行时多态性的原理
    • 在Rust中,动态分发是通过trait对象来实现运行时多态性的。trait对象允许在运行时根据对象的实际类型来决定调用哪个方法,而不是在编译时就确定。
    • 当我们创建一个trait对象(例如Box<dyn SomeTrait>)时,Rust会在运行时根据对象的实际类型查找对应的方法实现。这是因为trait对象在运行时会携带一个虚表(vtable),虚表中存储了实际类型对应的方法指针。
  2. 定义trait
    // 定义一个trait
    trait Animal {
        fn speak(&self);
    }
    
    上述代码定义了一个名为Animal的trait,它有一个方法speak,该方法没有具体实现,要求实现Animal trait的类型必须实现speak方法。
  3. 实现trait
    struct Dog;
    struct Cat;
    
    impl Animal for Dog {
        fn speak(&self) {
            println!("Woof!");
        }
    }
    
    impl Animal for Cat {
        fn speak(&self) {
            println!("Meow!");
        }
    }
    
    这里定义了两个结构体DogCat,并分别为它们实现了Animal trait的speak方法。
  4. 创建和使用trait对象来达成动态分发
    fn main() {
        let animals: Vec<Box<dyn Animal>> = vec![Box::new(Dog), Box::new(Cat)];
        for animal in animals {
            animal.speak();
        }
    }
    
    main函数中,创建了一个Vec,其中的元素是Box<dyn Animal>类型的trait对象,分别放入了DogCat的实例。在遍历这个Vec时,调用speak方法,由于动态分发,实际调用的是DogCat对应的speak方法实现,从而实现了运行时多态性。