我有一组需要相互了解才能合作的对象。这些对象存储在容器中。我试图对如何用 Rust 构建我的代码有一个非常简单的想法。
让我们打个比方。 AComputer
包含:
In Rust:
struct Computer {
mmu: Mmu,
ram: Ram,
cpu: Cpu,
}
为了使任何事情发挥作用,Cpu
需要了解Mmu
它链接到,并且Mmu
需要知道Ram
它链接到。
I do not想要Cpu
to 按值聚合 the Mmu
。它们的寿命不同:Mmu
可以自己过自己的生活。只是碰巧我可以将它插入Cpu
。然而,创建一个Cpu
没有Mmu
依附于它,因为它无法完成它的工作。之间也存在同样的关系Mmu
and Ram
.
所以:
- A
Ram
可以自己生活。
- An
Mmu
需要一个Ram
.
- A
Cpu
需要一个Mmu
.
我怎样才能在 Rust 中模拟这种设计,一个一个结构体,其字段相互了解.
在 C++ 中,它的结构如下:
>
struct Ram
{
};
struct Mmu
{
Ram& ram;
Mmu(Ram& r) : ram(r) {}
};
struct Cpu
{
Mmu& mmu;
Cpu(Mmu& m) : mmu(m) {}
};
struct Computer
{
Ram ram;
Mmu mmu;
Cpu cpu;
Computer() : ram(), mmu(ram), cpu(mmu) {}
};
以下是我开始用 Rust 翻译它的方式:
struct Ram;
struct Mmu<'a> {
ram: &'a Ram,
}
struct Cpu<'a> {
mmu: &'a Mmu<'a>,
}
impl Ram {
fn new() -> Ram {
Ram
}
}
impl<'a> Mmu<'a> {
fn new(ram: &'a Ram) -> Mmu<'a> {
Mmu {
ram: ram
}
}
}
impl<'a> Cpu<'a> {
fn new(mmu: &'a Mmu) -> Cpu<'a> {
Cpu {
mmu: mmu,
}
}
}
fn main() {
let ram = Ram::new();
let mmu = Mmu::new(&ram);
let cpu = Cpu::new(&mmu);
}
这很好,但现在我只是找不到一种方法来创建Computer
struct.
我开始于:
struct Computer<'a> {
ram: Ram,
mmu: Mmu<'a>,
cpu: Cpu<'a>,
}
impl<'a> Computer<'a> {
fn new() -> Computer<'a> {
// Cannot do that, since struct fields are not accessible from the initializer
Computer {
ram: Ram::new(),
mmu: Mmu::new(&ram),
cpu: Cpu::new(&mmu),
}
// Of course cannot do that, since local variables won't live long enough
let ram = Ram::new();
let mmu = Mmu::new(&ram);
let cpu = Cpu::new(&mmu);
Computer {
ram: ram,
mmu: mmu,
cpu: cpu,
}
}
}
好吧,无论如何,我将无法找到一种方法来引用它们之间的结构字段。我想我可以通过创建来想出一些东西Ram
, Mmu
and Cpu
在堆上;并将其放入结构中:
struct Computer<'a> {
ram: Box<Ram>,
mmu: Box<Mmu<'a>>,
cpu: Box<Cpu<'a>>,
}
impl<'a> Computer<'a> {
fn new() -> Computer<'a> {
let ram = Box::new(Ram::new());
// V-- ERROR: reference must be valid for the lifetime 'a
let mmu = Box::new(Mmu::new(&*ram));
let cpu = Box::new(Cpu::new(&*mmu));
Computer {
ram: ram,
mmu: mmu,
cpu: cpu,
}
}
}
是的,没错,此时 Rust 无法知道我要转让所有权let ram = Box::new(Ram::new())
to the Computer
,所以它将得到一生'a
.
我一直在尝试各种或多或少的黑客方法来实现这一点,但我就是无法想出一个干净的解决方案。我最接近的是放弃参考并使用Option
,但是我所有的方法都必须检查是否Option
is Some
or None
,这是相当难看的。
我想我只是走错了路,试图在 Rust 中映射我在 C++ 中要做的事情,但这不起作用。这就是为什么我需要帮助找出创建此架构的惯用 Rust 方法。