0

I want to create driver mappings for some Unix devices. To efficiently access the driver files, I want to keep the file handle opened after the first access, so I want to store an access wrapper in a map. Each device has different (but sometimes common) methods.

In an OOP-based language like Java, I would create an abstract class with this map and derivatives that access this map.

class Attribute {
    void doSomething() { /* Do Something */ }
}

abstract class Device {
    Map<String, Attribute> attributes = new HashMap<>();
}

class Motor extends Device {
    void func1() {
        attributes.get("elem1").do_something();
    }
}

class SpecialMotor extends Motor {
    void func2() {
        attributes.get("elem2").do_something();
    }
}

class Sensor extends Device {
    void func1() {
        attributes.get("elem1").do_something();
        // Its possible that this function has a different return type
    }
}

As far as I know, this is not possible in Rust. I tried to emulate this behavior with a trait to access this map, but this creates a lot of boilerplate code for each device.

struct Attribute {}
impl Attribute {
    fn do_something() {}
}

trait Device {
    fn get_attributes(&self) -> HashMap<String, Attribute>;
}

trait Motor: Device {
    fn func1(&self) {
        self.get_attributes()["elem1"].do_something();
    }
}

trait SpecialMotor: Motor {
    fn func2(&self) {
        self.get_attributes()["elem2"].do_something();
    }
}

trait Sensor: Device {
    fn func1(&self) {
        self.get_attributes()["elem1"].do_something();
    }
}

struct MotorImpl {
    attributes: HashMap<String, Attribute>,
}
impl MotorImpl {
    fn new() -> MotorImpl {
        MotorImpl {
            attributes: HashMap::new(),
        }
    }
}
impl Motor for MotorImpl {
    fn get_attributes(&self) -> HashMap<String, Attribute> {
        self.attributes
    }
}

struct SpecialMotorImpl {
    attributes: HashMap<String, Attribute>,
}
impl SpecialMotorImpl {
    fn new() -> SpecialMotorImpl {
        SpecialMotorImpl {
            attributes: HashMap::new(),
        }
    }
}
impl SpecialMotor for SpeicalMotorImpl {
    fn get_attributes(&self) -> HashMap<String, Attribute> {
        self.attributes
    }
}

struct SensorImpl {
    attributes: HashMap<String, Attribute>,
}
impl SensorImpl {
    fn new() -> SensorImpl {
        SensorImpl {
            attributes: HashMap::new(),
        }
    }
}
impl Sensor for SensorImpl {
    fn get_attributes(&self) -> HashMap<String, Attribute> {
        self.attributes
    }
}

Is it possible have a kind of common attribute for multiple traits or is there an even better design pattern to achieve this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
pixix4
  • 1,271
  • 1
  • 13
  • 13
  • 5
    Rust tends to favor using composition over inheritance. Trying to imitate the latter using traits rarely gives good results - traits are better suited to describing something an object *does* rather than something it *is*. – Joe Clay Jun 20 '18 at 13:20
  • 1
    I think this question is adequately answered by the answers to [Is it possible to access struct fields from within a trait?](https://stackoverflow.com/q/28219730/3650362) In short, no, it's not possible for traits to have fields. – trent Jun 20 '18 at 17:17
  • 2
    I found [this](https://doc.rust-lang.org/book/second-edition/ch17-03-oo-design-patterns.html) chapter in the book very useful (To not think in terms of OO in rust lang), when I moved from Java to Rust lang. – tsatiz Jun 20 '18 at 17:21

0 Answers0