How extract concrete value from Option<Box<dyn Any>>?

Hi,

I am Be Hai from Melbourne, Australia. I am very new to Rust, less than 30 days.

I have run into a problem: I would like to my Executor trait, execute() method to be able to return values of different data type.

I go with Option<Box<dyn Any>> -- I do realise that is a bit less efficient.

After calling this method on Actor1, I would like to extract the return value 234 to a u32 variable and so on.

I don't know how to do this.

Would you be able to help, please?

Thank you and best regards.

...behai.

use std::any::Any;

pub trait Executor {
    fn execute(&self) -> Option<Box<dyn Any>>;
}

pub struct Actor1 {}

pub struct Actor2 {}

pub struct Actor3 {}

impl Executor for Actor1 {
    fn execute(&self) -> Option<Box<dyn Any>> {
        Some(Box::new(234))
    }
}

impl Executor for Actor2 {
    fn execute(&self) -> Option<Box<dyn Any>> {
        Some(Box::new(12.04))
    }
}

impl Executor for Actor3 {
    fn execute(&self) -> Option<Box<dyn Any>> {
        Some(Box::new(String::from("Test string.")))
    }
}

fn main() {
    let actor = Actor1{};
    let result = actor.execute();
    println!("actor.execute(): {:?}", result);
    
    // TO_DO: how to 'extract' 234 to a u32 variable, please?

    let actor = Actor2{};
    let result = actor.execute();
    println!("actor.execute(): {:?}", result);

    // TO_DO: how to 'extract' 12.04 to a f32 variable, please?

    let actor = Actor3{};
    let result = actor.execute();
    println!("actor.execute(): {:?}", result);    

    // TO_DO: how to 'extract' "Test string." to a string variable, please?
}

You need an associated type.

pub trait Executor {
    type Output;
    fn execute(&self) -> Option<Self::Output>;
}

impl Executor for Actor1 {
    type Output = i32;
    fn execute(&self) -> Option<Self::Output> {
        Some(234)
    }
}
4 Likes

To give a more direct answer to the question, the method you are looking for is downcast() (see also the similar downcast() methods for different types of dyn Any reference). However, that requires you to know the correct concrete type or be prepared to handle the error case if the concrete type isn't what you need it to be.

The solution of using an associated type makes much better use of the static typing of Rust, since it allows the implementation to state what type it returns, and the compiler can check that you are only using Executor instances that return the correct type. A dyn Any approach could be better in a case where you really need the dynamicity it creates, and you can deal with the uncertainty of the actual return type. Such cases are particularly specific though, so we would need to know your use case to decide if it would be appropriate or if there is a better solution.

3 Likes

Hi mdHMUpeyf8yluPfXI,

Thank you very much for your helps. This precisely what I am looking for.

Thank you again and best regards,

...behai.

Hi jameseb7,

Thank you very much for your kind explanation. I can understand what you mean.

-- Clearly, I have not fully understood Using Trait Objects That Allow for Values of Different Types in 'the book'.

In this particular case, I need to work with just a few concrete types. So associated type is much better and makes much more sense.

Thank you and best regards,

...behai.

1 Like

Hi, quick tip with quotations in this forum. Seems like you’re (at least partially) hand-writing your [quote] blocks. Note that the post: 123 field is meant to refer to the number of the post being quoted; yours are a bit off, with the effect of the linking in this thread being a bit weird (your replies appear as replies to themself, and the quotations don’t jump to the correct post - I've edited the references in your replies, but doing that after the fact only seems to fix the latter).

Note that quotations can be easily created by highlighting text and pressing the quote button:

For example, while writing this, I’m highlighting something in your reply

and pressing the “Quote” button that appears (of course you won’t have an “Edit” button next to it, for other people’s posts) results in a quotation like this being inserted:

1 Like

Hi steffahn,

You are right. I did partially hand-write my quote blocks. I do apologise for that.

And thank you for your tip. I appreciate the information.

Thank you and best regards,

...behai.