面试题答案
一键面试- 设计思路:
- Trait定义:定义
Drawable
trait,包含渲染所需的方法,比如draw
方法。所有图形类型(圆形、矩形、三角形等)都实现这个trait
,这利用了Rust的trait实现多态性。 - 存储方式:为了提高性能,使用
Vec<Box<dyn Drawable>>
来存储多种图形。Box<dyn Drawable>
是一种胖指针,包含了指向对象数据的指针和指向vtable(虚表,存储了对象实现的trait方法的指针)的指针。这样在遍历图形集合进行渲染时,可以通过虚表找到对应的draw
方法。 - 遍历优化:在渲染大量图形时,尽量减少不必要的内存分配和动态调度开销。例如,可以通过
for
循环遍历Vec<Box<dyn Drawable>>
,直接调用draw
方法,避免过多的中间层调用。 - 代码组织:将不同图形的实现放在不同的模块中,保持代码的清晰和可维护性。同时,通过trait对象的方式,可以方便地添加新的图形类型,只需要让新类型实现
Drawable
trait即可,保证了扩展性。
- Trait定义:定义
- 关键代码结构:
// 定义Drawable trait
trait Drawable {
fn draw(&self);
}
// 圆形实现Drawable trait
struct Circle {
radius: f32,
}
impl Drawable for Circle {
fn draw(&self) {
println!("Drawing a circle with radius {}", self.radius);
}
}
// 矩形实现Drawable trait
struct Rectangle {
width: f32,
height: f32,
}
impl Drawable for Rectangle {
fn draw(&self) {
println!("Drawing a rectangle with width {} and height {}", self.width, self.height);
}
}
fn main() {
let mut shapes: Vec<Box<dyn Drawable>> = Vec::new();
shapes.push(Box::new(Circle { radius: 5.0 }));
shapes.push(Box::new(Rectangle { width: 10.0, height: 5.0 }));
for shape in &shapes {
shape.draw();
}
}
在上述代码中:
- 首先定义了
Drawable
trait,它有一个draw
方法。 - 然后分别为
Circle
和Rectangle
结构体实现了Drawable
trait。 - 在
main
函数中,创建了一个Vec<Box<dyn Drawable>>
类型的shapes
向量,将Circle
和Rectangle
对象通过Box
包装后放入向量中。最后通过遍历向量调用每个对象的draw
方法进行渲染。这种设计利用了Rust的trait和多态性,既保证了性能,又兼顾了代码的可维护性和扩展性。