Reputation: 41
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
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