我正在try 使用一个特征Context
,它的不同实现允许Cell
以不同的方式访问它的所有者World
,如以下人工设计的示例代码(编译;playground here)所示:
struct Cell {
value: i32,
}
impl Cell {
fn evolve<'a>(&self, ctx: impl Context<'a>) -> Cell {
Cell {
value: self.value + ctx.get_rate()
}
}
}
struct World {
cell: Cell,
magic: i32,
}
impl World {
fn evolve_cell<'a, C: Context<'a>>(&'a self) -> Cell {
let ctx = C::new(self);
self.cell.evolve(ctx)
}
fn update(&mut self) {
self.cell = self.evolve_cell::<MagicContext>();
}
}
trait Context<'a> {
fn new(world: &'a World) -> Self;
fn get_rate(&self) -> i32;
}
struct MagicContext<'a> {
world: &'a World,
}
impl <'a> Context<'a> for MagicContext<'a> {
fn new(world: &'a World) -> Self {
MagicContext {
world
}
}
fn get_rate(&self) -> i32 {
self.world.magic
}
}
fn main() {
let mut world = World {
cell: Cell { value: 2 },
magic: 3,
};
world.update();
println!("{}", world.cell.value);
}
我希望能够在main
中 Select 调用点的实现,而不是将MagicContext
指定为World::update
中的Context
实现--如下所示:
impl World {
// ...
fn update<C: Context>(&mut self) {
self.cell = self.evolve_cell::<C>();
}
}
// ...
fn main() {
// ...
world.update::<MagicContext>();
// ...
}
但是Context
需要一个生命周期参数.我不能引入像fn update<'a, C: Context<'a>>(&mut self)
这样的生命周期参数,因为上下文的生命周期将阻止我Mutations self
:
error[E0506]: cannot assign to `self.cell` because it is borrowed
--> lifetime.rs:25:9
|
24 | fn update<'a, C: Context<'a>>(&'a mut self) {
| -- lifetime `'a` defined here
25 | self.cell = self.evolve_cell::<C>();
| ^^^^^^^^^^^^-----------------------
| | |
| | borrow of `self.cell` occurs here
| | argument requires that `*self` is borrowed for `'a`
| assignment to borrowed `self.cell` occurs here
一些看似相似的问题让我看了一下更高等级的特征界限,大约是fn update<C: for <'a> Context<'a>>(&mut self)
分,但编译器告诉我:
error: implementation of `Context` is not general enough
--> lifetime.rs:56:11
|
56 | world.update::<MagicContext>();
| ^^^^^^ implementation of `Context` is not general enough
|
= note: `Context<'0>` would have to be implemented for the type `MagicContext<'_>`, for any lifetime `'0`...
= note: ...but `Context<'1>` is actually implemented for the type `MagicContext<'1>`, for some specific lifetime `'1`
我希望能够完全摆脱Context
的生命周期参数,但如果没有它,我不知道如何表达new
函数.
我如何才能做到这一点(或者以一种更惯用的方式实现某种类似功能)?