如何初始化相互引用的结构字段 [英] How to initialize struct fields which reference each other
问题描述
我目前想使用 GamerIterator 为 Piston 游戏定义一个结构:
I currently want to define a struct for a Piston game using GamerIterator:
pub struct MyGame<'a> {
game_window: GameWindowGLFW,
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
GameIterator
在 GameWindow
及其生命周期中是通用的.我想告诉编译器它与字段game_window"/整个结构"具有相同的生命周期,而忽略结构的生命周期.
The GameIterator
is generic in the GameWindow
and its lifetime. I want to tell the compiler that it has the same lifetime as the field "game_window"/"the whole struct" and leave out the lifetime for the struct.
我也很难初始化:
MyGame {
game_window: GameWindowGLFW::new(GameWindowSettings {/*...*/},
game_iter: GameIterator::new(&mut game_window, &game_iter_settings), // game_window cannot be used here
//...
}
我认为我可以通过使用 Option<GameIterator<...>>
和 init() 方法来解决初始化问题,但我想避免这种情况,因为我可以保证 game_iter
在 new()
完成后存在.
I think that I can work around the initialization issue by using Option<GameIterator<...>>
and an init() method, but I would like to avoid this because I can guarantee that game_iter
is present after new()
finishes.
写这个的惯用方式是什么?
What is the idiomatic way to write this?
推荐答案
如果 GameIterator
实现了 Drop
:编译器必须知道它需要在 game_window
之前销毁 game_iter
,否则 game_window
将引用被销毁的 GameWindowGLFW
同时运行其 drop()
方法.
Not only is there an issue with initialization, there could also be issues with destruction, if GameIterator
implemented Drop
: the compiler would have to know that it needs to destruct game_iter
before game_window
, otherwise game_window
would have a reference to a destroyed GameWindowGLFW
while running its drop()
method.
没有办法将结构本身的生命周期作为生命周期参数传递.您唯一能做的就是从 MyGame
中删除 game_window
字段并将 GameWindowGLFW
实例传递给 MyGame
的初始化程序.如果你想封装它以便用户不需要创建 GameWindowGLFW
,你可以编写一个方法来创建一个 GameWindowGLFW
和一个 MyGame
并调用仅接受 MyGame
参数的闭包.
There's no way to pass the lifetime of the struct itself as a lifetime argument. The only thing you can do is remove the game_window
field from MyGame
and pass a GameWindowGLFW
instance to MyGame
's initializer. If you want to encapsulate this so that the user doesn't need to create a GameWindowGLFW
, you could write a method that creates a GameWindowGLFW
and a MyGame
on the stack and calls a closure that accepts a MyGame
argument only.
pub struct MyGame<'a> {
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
impl<'a> MyGame<'a> {
fn new(game_window: &'a mut GameWindowGLFW) -> MyGame<'a> {
MyGame {
game_iter: GameIterator { game_window: game_window },
}
}
}
fn start_game(callback: |game: &mut MyGame|) {
let mut game_window = GameWindowGLFW;
let mut game = MyGame::new(&mut game_window);
callback(&mut game);
}
fn main() {
start_game(|game| {
/* use game here */
});
}
这篇关于如何初始化相互引用的结构字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!