我正在写一个简单的Rust游戏,其中包含一个Drawer
,它构造一次然后作为可变参考传递给许多方法:
pub struct Drawer<'a> {
// ...
renderer: Renderer<'a>,
// ...
}
fn pause(drawer: &mut Drawer, events: &[Event]) {
// ...
drawer.draw_text(&TextPos::Centered, "Paused", 1);
// ...
}
我想重构我的代码,为绘制文本引入流畅的界面,例如:
drawer.text()
.size(4)
.centered()
.draw("Paused");
我是通过创建TextDrawer
结构来实现的,该结构包含对Drawer
的引用:
pub struct TextDrawer<'a, 'b: 'a> {
pos: TextPos,
size: u32,
drawer: &'a mut Drawer<'b>,
}
impl<'a> Drawer<'a> {
pub fn text(&mut self) -> TextDrawer {
TextDrawer {
pos: TextPos::At(0, 0),
size: 1,
drawer: self,
}
}
}
我认为我在结构上的生命周期是正确的(引用必须与Drawer
本身一样长。)
但是,在添加显式生存期之前,我的text
方法不会编译。当我这样做时,每个调用text
的方法都需要明确的生命周期,依此类推。我很惊讶这些生命周期必须说明:毕竟,它们都是fn foo<'a, 'b: 'a>(drawer: &mut'a Drawer<'b>)
的形式。在此之前我曾假设这已经是推断的生命周期,因为引用始终需要与Drawer
本身一样长。
我是否有必要将这些明确的生命周期放在我的方法签名上?或者我可以通过其他方式避免它吗?
答案 0 :(得分:1)
感谢上面Lukas提出的minimal example,我意识到我只是向我的text
方法提取了生命周期参数。
我的生命时间不正确:
impl<'a> Drawer<'a> {
pub fn text<'b>(&'b mut self) -> TextDrawer<'a, 'b> {
// omitted
}
}
正确的生命周期:
impl<'a> Drawer<'a> {
pub fn text<'b>(&'b mut self) -> TextDrawer<'b, 'a> {
// omitted
}
}
在此之后,一切都在没有任何明确的生命周期的情况下进行编译。