วิธีรับ & dyn T จากกล่อง <dyn T> [ซ้ำ]

Jan 11 2021

ฉันกำลังพยายามหา a &dyn TจากBox<dyn T>ตัวอย่างต่อไปนี้ อย่างไรก็ตามไม่สามารถรวบรวม

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)

ข้อความแสดงข้อผิดพลาดคือ

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`

เป็นที่ชัดเจนว่าคุณจะได้รับ&Tจากไฟล์Box<T>. ฉันไม่เข้าใจว่าทำไมคุณไม่สามารถรับไฟล์&dyn Tจากไฟล์Box<dyn T>.

คำตอบ

2 kmdreko Jan 11 2021 at 07:22

หากต้องการรับ&dyn Tจาก a Box<dyn T>ให้ใช้&*:

let c: &dyn MyTrait = &*b;

*จะใช้ในการderefกล่องลงในเนื้อหาของ ( dyn MyTrait) และจากนั้น&จะใช้ในการได้รับมันเป็นข้อมูลอ้างอิง


นี่เป็นวิธีที่ "ถูกต้อง" ในการรับไฟล์&Fooจากไฟล์Box<Foo>. เหตุผลที่&bทำงานร่วมกับประเภทคอนกรีตเป็นเพราะDerefลักษณะช่วย&Box<T>ที่จะข่มขู่เพื่อ&T:

หาก T ใช้ Deref <Target = U> และ x เป็นค่าประเภท T ดังนั้น:

  • ค่าของประเภท & T ถูกบังคับให้เป็นค่าประเภท & U

เหตุผลที่ใช้ไม่ได้กับวัตถุลักษณะนั้น&dyn MyTrait อาจใช้ได้&Box<...>และการบังคับไม่ได้พยายามแม้ว่าจะล้มเหลว