简体   繁体   中英

Allow variable to have any trait implementation

I have a program which interfaces with slightly different hardware. All hardware types support the same features which can be encapsulated in a trait.

I would like to assign the hardware used based on an argument to the program.

A minimal version of what I would try to achieve is the following

trait Hardware{
     ...
}

impl Hardware for HardwareTypeOne{
    ...
}
impl Hardware for HardwareTypeTwo{
    ...
}
fn do_stuff_with_hw(hw &mut impl Hardware){
    ...
}
fn main(){
    ...
    let hw = match args{
        arg_types::hw_1 => HardwareTypeOne,
        arg_types::hw_2 => HardwareTypeTwo,
    };
    hw.run_something();
    do_stuff_with_hw(&hw)
}

This of course won't work as the compiler will complain about not knowing the size of the hw variable at compile time.

I tried implementing this using boxing

Using if/else i was able to get this to work

let hw:Box<dyn Hardware>
if args == arg_types::hw_1{
    hw = Box::new(HardwareTypeOne);
}
else{
    hw = Box::new(HardwareTypeTwo);
}

But running:

hw.run_somenthing()
do_stuff_with_hw(&hw)

then won't work since the type has changed. And trying to "unbox" the variable will of course give the same error, complaining about the size not being known.

How does one go about doing something like this in rust? I would like to avoid having to compile different versions of the software for different implementations.

This can work, with a few fixes:

trait Hardware {
    fn run_something(&self);
}

struct HardwareTypeOne;
struct HardwareTypeTwo;

impl Hardware for HardwareTypeOne {
    fn run_something(&self) {
        println!("run_something type one");
    }
}

impl Hardware for HardwareTypeTwo {
    fn run_something(&self) {
        println!("run_something type two");
    }
}

fn do_stuff_with_hw(_hw: &mut (impl Hardware + ?Sized)) {
}

fn main() {
    let mut hw: Box<dyn Hardware> = match true {
        true => Box::new(HardwareTypeOne),
        false => Box::new(HardwareTypeTwo),
    };
    
    hw.run_something();
    do_stuff_with_hw(&mut *hw);
}
  • hw in main() must be declared mut in order to obtain a mutable reference to the value in the box.
  • You need to use the syntax &mut *hw to obtain a mutable reference to the value inside the box.
  • You need to relax the implicit Sized constraint on do_stuff_with_hw 's argument type by adding the ?Sized constraint; this allows it to be invoked with a &mut dyn Hardware . (Alternatively, you can have the method take &mut dyn Hardware instead of &mut impl Hardware .)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM