我最近学习了 Rust,对于我的第一个大型实践项目,我正在使用
crossterm
制作一个基于终端的游戏。现在,我来自 Java 和 C++ 的 OOP 世界,所以我在适应 Rust 时遇到了一些困难。
如果我用 OOP 语言制作这个,我会有一个
GameWorld
抽象类来定义不同的“世界”,例如大厅、元世界、地下城和菜单。 GameWorld
将具有 draw()
和 tick()
等方法。
然后,对于每个世界,我都会定义一个子类,所以我会有
DungeonWorld
和 MenuWorld
等等...
然而,在 Rust 中,我最初的想法是定义一个
World
特征。然后我可以为每个世界定义结构并让它们实现World
。但这需要大量使用Box<dyn World>
,这似乎受到社区的劝阻并且执行缓慢。
理论上,我希望能够为
impl
结构的每个实例定义不同的 World
块。
这是我目前拥有的精简版。
let game = game::get_game();
loop {
let result = if event::poll(std::time::Duration::from_millis(1000 / TICK_SPEED))
.expect("Error checking input")
{
game.current_world.update(Some(event::read().expect("Error reading input.")))
} else {
game.current_world.update(None)
};
if !result {
break;
}
game.curent_world.draw();
}
////////////
pub trait World {
fn draw(&self);
fn update(&self, event: Option<Event>);
}
////////////
struct Game {
current_world: Box<dyn World>,
}
struct MenuWorld {}
impl World for MenuWorld {
fn draw(&self) {}
fn update(&self, event: Option<Event>) {}
}
pub fn get_game() -> Game {
Game {
current_world: Box::new(MenuWorld {})
}
}
我想我已经解决了这个问题,有两种解决方案
a)使用类似这个板条箱的东西https://docs.rs/enum_dispatch/latest/enum_dispatch/
b) 继续
Box<dyn World>
,因为它并没有那么糟糕,而且是其他语言在幕后所做的事情。