Как создать коллекцию типизированных структур в Rust? - PullRequest
0 голосов
/ 02 сентября 2018

Я создаю текстовую монопольную игру в 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, поэтому не всегда знаю, что искать.

1 Ответ

0 голосов
/ 02 сентября 2018

Компилятору Rust необходимо знать, насколько большим будет каждый элемент в вашем Vec, чтобы решить, как планировать память (каждый элемент должен занимать одинаковое количество места). Ваша Space структура имеет параметр типа T, поэтому неясно, сколько места займет Space, если вы также не укажете параметр типа. Например. Vec<Space<i32>> будет работать.

Если вы хотите Vec объектов разного размера, общий подход заключается в использовании вектора признаков . В вашем примере у вас может быть 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
...