Aram Hayrapetyan
Aram Hayrapetyan

Reputation: 41

Rust: Trait as a return type

Lets say there's this kind of code:

trait A {
  fn something(&self) -> String
}

struct B {
  things: Vec<u64>
}

struct C {
  thing: Box<&dyn A>
}

impl A for B { ... }

fn create_thing() -> B {
  // 
}

impl C {
  pub fn new() {
    let thing = create_thing();
    C { thing }
  }
}

My question is what exactly should be the return type of create_thing to match with Box<&dyn A> or how exactly should the returning value be wrapped to match with Box<&dyn A>?

Equivalent C# code would look something like:

interface A {}
class B : A {}
class C {
  public A field;
  public C() {
    this.field = new B();
  }
}

Upvotes: 1

Views: 1149

Answers (1)

prog-fh
prog-fh

Reputation: 16920

Find below your code with minor adjustments to get it to compile.

I suspect that Box<&dyn A> was not intended since it means that the reference itself is heap-allocated (not the referred to object). On the other hand, Box<dyn A> matches your C# example.

The return type create_thing() looks good to me because it does not assume any particular kind of storage (stack, heap, inside a vector...) for the returned value. You just have to Box this resulting value in order to provide it when initialising a C.

However, if you want to hide the fact that the exact returned type is B in create_thing(), you can change it like this fn create_thing() -> impl A.

If you really want to return a dyn trait object, then change it to fn create_thing() -> Box<dyn A> and create the box here rather than in C::new().

trait A {
    fn something(&self) -> String;
}

struct B {
    things: Vec<u64>,
}

struct C {
    thing: Box<dyn A>,
}

impl A for B {
    fn something(&self) -> String {
        format!("something on B with {:?}", self.things)
    }
}

fn create_thing() -> B {
    B {
        things: vec![1, 2, 3],
    }
}

impl C {
    pub fn new() -> Self {
        let thing = Box::new(create_thing());
        Self { thing }
    }
}

fn main() {
    let c = C::new();
    println!("{}", c.thing.something());
}

Upvotes: 3

Related Questions