3

this is my first post on here, and I'm wondering about a good rust implementation with traits on enum types. I want to know if using an enum w/ a trait as a generator of different code is viable like the one below? Also a couple of things I'm curious about is if there is an overhead with the match statement? Would implementing separate structs be faster?

struct GeneralCell {
 repr: char,
 position: Position,
 cell_type: Cell,
}
trait InitializeCells {
 fn new(&self, position: Position) -> GeneralCell;
}
pub enum Cell {
 Hall,
 Filled,
 Empty,
}
impl InitializeCells for Cell {
 fn new(&self, position: Position) -> GeneralCell {
 match self {
 Cell::Hall => GeneralCell {
 repr: 'H',
 position,
 cell_type: Cell::Hall,
 },
 Cell::Empty => GeneralCell {
 repr: 'E',
 position,
 cell_type: Cell::Empty,
 },
 Cell::Filled => GeneralCell {
 repr: 'F',
 position,
 cell_type: Cell::Filled,
 },
 }
 }
}
asked Jun 29, 2020 at 17:07
2
  • 2
    How would this be used? What are the design goals? Why are you introducing a trait when you could impl the method directly? Note that design-level questions are on-topic here, but if you're more interested in code-level help. Stack Overflow would be the better address. Commented Jun 29, 2020 at 18:43
  • Hi, thanks for the reply. I think you answered my question(partially). So this is more of a toy example of me trying the best way to learn the language with code re-usability(as I'm still a Rust noob). I didn't know if traits were used like this. I'm trying to create a randomly generated dungeon, with a variable amount of different cell types. If I create many different types(like 50+), would matching be the best way to go about it(with one struct to hold all the general info). What would be the best way to bind specific cell behaviors. More matching? Commented Jun 29, 2020 at 22:09

1 Answer 1

3

I think there are two ways I would consider implementing this:

Using an enum

This is usually the appropriate design, in particular when you know all possible types up front. A benefit is the strong type checking, as you will be warned if a match forgets to handle a particular type.

pub enum Cell {
 Hall,
 Filled,
 Empty,
}
impl Cell {
 pub fn get_char(&self) -> char {
 match self {
 Self::Hall => 'H',
 Self::Filled => 'F',
 Self::Empty => 'E',
 }
 }
}

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=eff909882165138262a103e5d075f1f1

Using a trait

This is a more flexible design, and allows you to more easily add new cell types later. You can also more easily add custom behaviour to cells. However, you now have to use trait objects, e.g. by storing the cell type as Box<dyn Cell>.

pub trait Cell {
 // If the char only depends on the type of cell, you can remove the `&self`.
 fn get_char(&self) -> char;
}
struct Hall;
impl Cell for Hall {
 fn get_char(&self) -> char {
 'H'
 }
}
struct Filled;
impl Cell for Filled {
 fn get_char(&self) -> char {
 'F'
 }
}
struct Empty;
impl Cell for Empty {
 fn get_char(&self) -> char {
 'E'
 }
}

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c5fdd7e1669814f3db04eacd9f43fa1b

amon
136k27 gold badges295 silver badges386 bronze badges
answered Jul 1, 2020 at 16:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.