Strategy using traits

I am having trouble finding the right approach to my following problem.

I have two structs Foo and Bar which both implement MyTrait but only Foo also implements MyOtherTrait

A struct Storage stores Foo and the field data which takes Vec<Box<dyn MyTrait>>

When I access data I can use all methods of MyTrait given my definition of Storage

How do I access all functions of Foo in this case? What is a good approach here?

trait MyTrait {
    fn give_number(&self,i: i32) -> i32; 

trait MyOtherTrait {
    fn hello(&self) -> String;

struct Foo{}
struct Bar{}

impl Foo {}

impl MyTrait for Foo {
    fn give_number(&self,i: i32) -> i32 {

impl MyOtherTrait for Foo {
    fn hello(&self) -> String {

impl MyTrait for Bar {
        fn give_number(&self,i: i32) -> i32 {

impl Bar {}

struct Storage {
    data: Vec<Box<dyn MyTrait>>,

fn main() {
    let s = Storage{data: vec![Box::new(Foo{}), Box::new(Bar{})]};
    println!("{:?}",[0].hello()) // compile error method not found in `std::boxed::Box<(dyn MyTrait + 'static)>`

I am a self taught rather inexperienced programmer and sometimes circle around "strategies" how to approach a problem. But rust really is showing me my limits...


You can downcast the type to Foo using Box::downcast.

What do MyTrait and MyOtherTrait represent? If you have a fixed number of implementors, it will be better to just use an enum instead of a trait.

Thanks for your swift reply. I have thought about this solution and asked a questions previously regarding downcasting.

Where I having trouble with is where to downcast? Would it make sense to implement something like get_foo in MyTrait?

If you're using this enough that you're considering making it part of the trait, I recommend making it an enum instead as suggested by @RustyYato

i.e. you could do something like

enum MyEnum {
    // ...

Then you can pattern match to get Foo

Thanks for your feedback.

I have also thought about this approach. But I am not 100% sure how to do this reasonable.

Let's say Foo and Bar share some methods. This would mean I have to pattern match Foo and Bar for every function, right?

Or do you mean I should implement something like get_foo using Enums?


If they share methods then you can add those methods to MyEnum

impl MyEnum {
    fn shared_method(&self) {
        match self {
            Self::Foo(foo) => foo.shared_method(),
            Self::Bar(bar) => bar.shared_method(),

Or you could even just inline those methods into MyEnum if you want. If you have a lot of these functions, you could use a macro to ease the boilerplate.


Great. I didn't know I could do this.

Really happy with this forum. Very helpful and patient with newbies.



Alternatively, if the implementation is the same, you could keep the trait and use a default implementation:

Thanks to both of you!

Another approach would be to store Foos in one Vec<Foo> and Bars in Vec<Bar>.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.