Jak uzyskać & dyn T z pudełka <dyn T> [duplikat]

Jan 11 2021

Próbuję uzyskać a &dyn Tod a Box<dyn T>, jak w poniższym przykładzie. Jednak nie można go skompilować.

trait MyTrait {
    
}

struct Foo;
impl MyTrait for Foo {}

fn main() {
    let b: Box<dyn MyTrait> = Box::new(Foo);
    let c: &dyn MyTrait = &b;
}

(https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=69c72904fbceae5b55470a878a441b7d)

Komunikat o błędzie to

error[E0277]: the trait bound `Box<dyn MyTrait>: MyTrait` is not satisfied
  --> src/main.rs:10:27
   |
10 |     let c: &dyn MyTrait = &b;
   |                           ^^ the trait `MyTrait` is not implemented for `Box<dyn MyTrait>`
   |
   = note: required for the cast to the object type `dyn MyTrait`

Oczywiste jest, że możesz uzyskać plik &Tz pliku Box<T>. Nie rozumiem, dlaczego nie możesz dostać &dyn Tod Box<dyn T>.

Odpowiedzi

2 kmdreko Jan 11 2021 at 07:22

Aby uzyskać &dyn Ta Box<dyn T>, użyj &*:

let c: &dyn MyTrait = &*b;

*Służy do deref okno do jego zawartości ( dyn MyTrait), a następnie &jest używana do pobierania go jako odniesienie.


Jest to również „właściwy” sposób uzyskania &Fooa Box<Foo>. Powodem, dla którego &bdziała z konkretnymi typami, jest to, że Derefcecha pozwala &Box<T>na zmuszenie do &T:

Jeśli T implementuje Deref <Target = U>, a x jest wartością typu T, to:

  • Wartości typu & T są przekształcane na wartości typu & U

Powodem, dla którego nie działa w przypadku obiektów cech, jest to, że &dyn MyTrait może to być ważne, &Box<...>a przymus nie jest podejmowany, nawet jeśli się nie powiedzie.