How to save an object unknown at compile time to a variable by pattern matching in Rust?

Viewed 78

TLDR; How do you make Rust's pattern matching behave dynamically like Python 3?

I'm quite new to Rust, and I struggle with a certain concept / code snippet. I'm trying to assign an object that is unknown at compile time to a variable using pattern matching. The different objects share a common trait, which contains the only methods I want to use on this object.

trait DoAction { fn action(&self); }

struct ObjectA { ... }
impl DoAction for ObjectA { fn action(&self) { ... } }

struct ObjectB { ... }
impl DoAction for ObjectB { fn action(&self) { ... } }

// This does not work
let object = match condition {
    true => ObjectA { ... },
    false => ObjectB { ... },
};

// I want to call this
object.action();

Working Python 3 example for comparison (what I want to achieve).

object = ObjectA(...) if true else ObjectB(...)

All help on this would be appreciated!

2 Answers

You can dynamically dispatch them,remember that for that you need to box your types:

let object: Box<dyn DoAction> = match condition {
    true => Box::new(ObjectA { ... }),
    false => Box::neww(ObjectB { ... }),
};

or

let object = match condition {
    true => Box::new(ObjectA { ... }) as Box<dyn DoAction>,
    false => Box::neww(ObjectB { ... }) as Box<dyn DoAction>,
};

Besides @Netwave's variants, there's a possibility to cast the objects to &dyn DoAction, without dealing with heap allocation of Box

trait DoAction { fn action(&self); }

struct ObjectA {}
impl DoAction for ObjectA { 
    fn action(&self) { println!("A"); } 
}

struct ObjectB { }
impl DoAction for ObjectB { 
    fn action(&self) { println!("B"); } 
}
fn main() {
    let condition = true;
    let object = match condition {
        true => &ObjectA{} as &dyn DoAction,
        false => &ObjectB{} as &dyn DoAction,
    };
    
    object.action(); // prints "A"
}
Related