面试题答案
一键面试1. 什么是trait的对象安全
在Rust中,当一个trait可以用于trait对象(例如 &dyn Trait
或 Box<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>
)。