使用RC的嵌套结构的Rust依赖性反转



我正试图在Rust中进行一些依赖性反转。我的目标是创建一个结构,它接受任何其他符合特征的结构实例。

这不会编译,但基本上是我想要实现的:

// Trait for any kind of tool I may use in my work
trait ToolTrait {
fn do_work(&self);
}
struct Saw {
size: i32,
}
impl ToolTrait for Saw {
fn do_work(&self) {
println!("I'm a saw, size: {}cm", self.size);
}
}
struct ScrewDriver {
size: i32,
}
impl ToolTrait for ScrewDriver {
fn do_work(&self) {
println!("I'm a screwdriver, size: {}mm", self.size);
}
}
// Work uses any struct that complies with ToolTrait
pub struct Work {
tool: ToolTrait,
}
impl Work {
// We can instantiate Work and set tool to it
fn new(tool: ToolTrait) -> Work {
Work { tool }
}
}
let saw = Saw { size: 30 };
let work_1 = Work::new(saw);
work_1.tool.do_work(); // "I'm a saw, size: 30cm"
let screwdriver = ScrewDriver { size: 4 };
let work_2 = Work::new(screwdriver);
work_2.tool.do_work(); // "I'm a screwdriver, size: 4mm"

现在,关于Rust编译器,我们有几个错误警告:

pub struct Work {
tool: ToolTrait,
}
// trait objects without an explicit `dyn` are deprecated

好的,让我们在Workimpl Work:中添加dyn

pub struct Work {
tool: dyn ToolTrait,
}
impl Work {
fn new(tool: dyn ToolTrait) -> Work {
Work {
tool: Rc::new(tool),
}
}
}

完美,Work中没有错误。但专注于impl Work,我们有一个错误:

impl Work {
fn new(tool: ToolTrait) -> Work {
Work {
tool: Rc::new(tool),
}
}
}
// the size for values of type `(dyn main::ToolTrait + 'static)` cannot be known at compilation time

有道理:Work不知道tool的大小。但我该怎么修呢?我用std::rc::Rc包裹了dyn ToolTrait作为Rc<dyn ToolTrait>:

pub struct Work {
tool: Rc<dyn ToolTrait>,
}
impl Work {
// We can instantiate Work and set tool to it
fn new(tool: Rc<dyn ToolTrait>) -> Work {
Work { tool }
}
}

这是可行的,但这是像我们在面向对象编程中通常做的那样实现依赖反转的正确方法吗?

您可以通过以下工具使您的结构通用

// Trait for any kind of tool I may use in my work
trait ToolTrait {
fn do_work(&self);
}
struct Saw {
size: i32,
}
impl ToolTrait for Saw {
fn do_work(&self) {
println!("I'm a saw, size: {}cm", self.size);
}
}
struct ScrewDriver {
size: i32,
}
impl ToolTrait for ScrewDriver {
fn do_work(&self) {
println!("I'm a screwdriver, size: {}mm", self.size);
}
}
// Work uses any struct that complies with ToolTrait
pub struct Work<T> {
tool: T,
}
impl<T: ToolTrait> Work<T> {
// We can instantiate Work and set tool to it
fn new(tool: T) -> Work<T> {
Work { tool }
}
}
fn main() {
let saw = Saw { size: 30 };
let work_1 = Work::new(saw);
work_1.tool.do_work(); // "I'm a saw, size: 30cm"
let screwdriver = ScrewDriver { size: 4 };
let work_2 = Work::new(screwdriver);
work_2.tool.do_work(); // "I'm a screwdriver, size: 4mm"
}

最新更新