MST
星途 面试题库

面试题:Rust中trait的对象安全相关基础

请阐述在Rust中,什么是trait的对象安全,需要满足哪些条件才能使一个trait是对象安全的,并举例说明一个对象安全和一个非对象安全的trait。
32.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

1. 什么是trait的对象安全

在Rust中,当一个trait可以用于trait对象(例如 &dyn TraitBox<dyn Trait>)时,这个trait就是对象安全的。trait对象允许在运行时动态地确定调用哪个具体类型的方法,实现多态性。

2. 对象安全需满足的条件

  • 方法的 Self 类型参数必须是 Self: Sized:这意味着方法不能依赖于具体类型的大小信息,因为trait对象在编译时大小是未知的。
  • 方法不能返回 Self:返回 Self 类型会要求知道具体类型的大小,而trait对象在编译时无法确定其具体类型大小。
  • 方法必须是对象安全的:递归地要求方法内部调用的所有方法也满足对象安全条件。

3. 对象安全的trait示例

trait Draw {
    fn draw(&self);
}

struct Rectangle;
impl Draw for Rectangle {
    fn draw(&self) {
        println!("Drawing a rectangle");
    }
}

struct Circle;
impl Draw for Circle {
    fn draw(&self) {
        println!("Drawing a circle");
    }
}

fn main() {
    let shapes: Vec<Box<dyn Draw>> = vec![
        Box::new(Rectangle),
        Box::new(Circle),
    ];
    for shape in shapes {
        shape.draw();
    }
}

在上述示例中,Draw trait 是对象安全的,因为 draw 方法接收 &self,没有返回 Self,且满足其他对象安全条件。

4. 非对象安全的trait示例

trait CloneMe {
    fn clone(&self) -> Self;
}

struct MyType(i32);
impl CloneMe for MyType {
    fn clone(&self) -> Self {
        MyType(self.0)
    }
}

// 以下代码会编译失败
// fn main() {
//     let values: Vec<Box<dyn CloneMe>> = vec![
//         Box::new(MyType(1)),
//     ];
// }

在这个例子中,CloneMe trait 是非对象安全的,因为 clone 方法返回 Self,不满足对象安全的条件,所以不能用于trait对象(如 Box<dyn CloneMe>)。