Jak uzyskać & dyn T z pudełka <dyn T> [duplikat]
Próbuję uzyskać a &dyn T
od 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 &T
z pliku Box<T>
. Nie rozumiem, dlaczego nie możesz dostać &dyn T
od Box<dyn T>
.
Odpowiedzi
Aby uzyskać &dyn T
a 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 &Foo
a Box<Foo>
. Powodem, dla którego &b
dział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.