我有以下结构:

struct Age(u8);
struct User {
    age: Age,
}

我想将User类型的借入值强制转换为&Age,如以下示例所示:
let s = String::from("abcd");
let z: &str = &s; // This works

let b = Box::new(Age(8));
let a: &Age = &b; // This also works

documentation for Borrow 提到如果A实现B,则可以借用A类型作为其他类型的Borrow<B>,因此我尝试为Borrow<Age>实现User:
use std::borrow::Borrow;

impl Borrow<Age> for User {
    fn borrow(&self) -> &Age {
        &self.age
    }
}

fn main() {
    let u = User { age: Age(8) };
    let a: &Age = u.borrow();     // Works
    let a: &Age = &u;             // Error
}

这是我收到的错误消息:

error[E0308]: mismatched types
  --> src/main.rs:23:19
   |
23 |     let a: &Age = &u; // Error: expected struct `Age`, found struct `User`
   |                   ^^ expected struct `example::Age`, found struct `example::User`
   |
   = note: expected type `&example::Age`
              found type `&example::User`

我想念什么吗?如何将&u强制转换为&Age

最佳答案

带有BoxString的两个示例的工作不是因为Borrow特性,而是因为Deref特性。您可以将示例中的&b框强制转换为&Age,因为Box<Age>实现了Deref<Target = Age>。同样,String具有Deref实现,因此可以将String引用&s强制转换为&str。它将以完全相同的方式为您的User工作:

use std::ops::Deref;

impl Deref for User { // That's bad, don't do that.
    type Target = Age;
    fn deref(&self) -> &Age {
        &self.age
    }
}

在此范围内,现在可以编译以下内容:
let u = User { age: Age(8) };
let a: &Age = &u;

请注意,该示例在某种程度上是人为的,而不是惯用的:没有人会期望User的行为类似于Age的指针类型。同样,没有人会期望user.borrow()借用Age而不是User,这不是Borrow特性的用途。

09-10 00:29
查看更多