我正在Rust中创建一个基于文本的垄断游戏作为个人项目。我目前的设置是将各种空间作为自己的结构(例如,Property
)
use space::Event;
pub struct Property {
message: String,
}
impl Property {
pub fn new() -> Property {
let message = String::from("Hello World!");
Property { message: message }
}
}
impl Event for Property {
fn event(&self) {
print!("{}", &self.message);
}
}
和一个通用的Space
结构,它包含一个空格类型的实例(例如Space<Property>
或Space<Chance>
)。
pub trait Event {
fn event(&self);
}
pub struct Space<T> {
item: T,
}
impl<T: Event> Space<T> {
pub fn new(item: T) -> Space<T> {
Space { item: item }
}
pub fn event(&self) {
&self.item.event();
}
}
每种类型的空间都实现了一个特征,要求它具有“事件”方法,通用Space结构可以调用该方法。然后我有一个Game
结构,它将包含某种空间集合(除其他外)。
pub struct Game {
spaces: Vec<Space>, // Does not work
}
不幸的是,我遇到了创建此集合的问题。无论我尝试哪一个,它都告诉我必须为Space指定一个类型参数。如何制作通常键入的结构集合?如果我可以通过其索引拉出一个特定的空间,那将是更好的选择,因为这将使我更容易实现某些Chance
卡,这些卡将您带到特定的空间后面。抱歉,如果我遗漏了一些明显的东西,我是Rust的新手,所以我并不总是知道要找什么。
Rust编译器需要知道Vec中每个元素的大小决定如何布局内存(每个元素必须占用相同的空间)。你的Space
结构有一个类型参数T
所以除非你提供类型参数,否则不清楚Space
将占用多少空间。例如。 Vec<Space<i32>>
会工作。
如果你想要一个不同大小的物体的Vec
,一个常见的方法是使用trait objects的矢量。在你的例子中,你可以有一个Vec<Box<Event>>
,一个实现Event
特征的对象向量,这里vec的每个元素都是一个Box(智能指针),用于实现Event
的堆分配类型。
pub trait Event {
fn event(&self);
}
pub struct Property {
message: String,
}
impl Property {
pub fn new(message: String) -> Property {
Property { message }
}
}
impl Event for Property {
fn event(&self) {
println!("{}", &self.message);
}
}
pub struct Utility {
message: String,
}
impl Utility {
pub fn new(message: String) -> Utility {
Utility { message }
}
}
impl Event for Utility {
fn event(&self) {
println!("{}", &self.message);
}
}
pub struct Game {
pub spaces: Vec<Box<Event>>,
}
fn main () {
let game = Game{
spaces: vec![
Box::new(Utility::new(String::from("Water works"))),
Box::new(Property::new(String::from("Fleet Street"))),
Box::new(Utility::new(String::from("Electric company"))),
Box::new(Property::new(String::from("Bond Street"))),
]
};
for space in game.spaces {
space.event();
}
}
// Water works
// Fleet Street
// Electric company
// Bond Street