6

Functions new_foo1 and new_foo2 return the same trait Foo using different patterns. I don't see any functional difference between them besides new_foo1 being more verbose. Is there a preferred way among the two? Is there any subtle ramifications of either pattern?

trait Foo {
    fn bar(&self);
}

struct FooIm {}

impl Foo for FooIm {
    fn bar(&self) {
        println!("bar from FooIm")
    }
}

fn new_foo1<'a>() -> &'a (dyn Foo + 'a) {
    &FooIm {}
}

fn new_foo2() -> Box<dyn Foo> {
    let f = FooIm {};
    Box::new(f)
}

fn main() {
    let f1 = new_foo1();
    let f2 = new_foo2();

    f1.bar();
    f2.bar();
}
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
Aleksey Kanaev
  • 293
  • 7
  • 13
  • 6
    The main difference should come along once you make `new_foo1` a bit more complicated than just returning a literal ([relevant question on the subject of returning references to local values](https://stackoverflow.com/q/50345139)). Try for example a `FooIm` that contains heap-allocated data such as a `Vec` or a `String`, and as described in the linked duplicate, only `new_foo2` will compile. – E_net4 Sep 22 '20 at 08:45
  • 1
    I see now. But why new_foo1 even exists, if it is so faint? – Aleksey Kanaev Sep 22 '20 at 09:27
  • 2
    @AlekseyKanaev Passing boxes around passes ownership. You often need to pass references around without giving up ownership. This is completely unrelated to trait objects. – Sven Marnach Sep 22 '20 at 09:40
  • 3
    A constructor should always returned an owned object, so in this case returing a reference indeed doesn't make any sense. – Sven Marnach Sep 22 '20 at 09:41
  • It's a shame that this got closed as a duplicate, because none of the 5 questions mentioned talk specifically about the dyn keyword, barely talk about dynamic dispatch, and some of them are completely irrelevant. If StackOverflow was more concerned with answering questions than closing them as duplicates maybe it wouldn't be losing most of its userbase. – SirDorius Aug 31 '23 at 22:44

0 Answers0