如何访问 dyn 结构体的字段?

The*_*eks 4 dynamic-dispatch rust

最近我一直在学习高级 Rust。作为其中的一部分,我正在学习使用动态调度。

在我的修补过程中,我遇到了一些问题。由于某种原因,我似乎无法访问已使用框和动态调度分配给变量的结构字段。例如,

fn main() {
    let z: Box<dyn S>;
    z = Box::new(A::new());

    println!("{}", z.val);
}

trait S {
    fn new () -> Self where Self: Sized;
}


struct A {
    val: i32,
}

impl S for A {
    fn new () -> A {
        A {val: 1}
    }
}

struct B {
    val: i32
}

impl S for B {
    fn new() -> B {
        B {val:2}
    }
}
Run Code Online (Sandbox Code Playgroud)

产生错误消息“错误[E0609]:val类型上没有字段Box<dyn S>

有什么方法可以访问这些字段,还是我需要拼凑一个解决方法?

Max*_*nko 5

如果您了解特征对象是什么,就很容易理解为什么这不起作用。当方法返回 a 时,dyn Trait它不会返回 any 的实例struct。相反,它返回一个查找表,告诉调用者在哪里可以找到它的方法。因此调用者可以在不了解底层struct本身的情况下访问方法。

因此,如果调用者无权访问其struct自身,那么很明显它无法访问其字段。

有两种方法可以实现您想要做的事情:

  1. 使用特征的方法来访问所需的字段。如果特征的可能实现者列表未预先确定,并且特征本身不太复杂(因为可以表示为特征对象的特征有一些限制),那么这是一个不错的选择。尽管特征对象会带来一些运行时开销(使用查找表比直接方法访问慢)。
  2. 使用enum。如果您知道该方法可以返回的选项的完整列表,那么它是最好且最 Rust 的解决方案。
enum S {
  A { val: i32, anotherAval: u32 },
  B { val: i32, anotherBval: f32 },
}

impl S {
  fn val(&self) -> i32 {
    match self {
      S::A => A.val,
      S::B => B.val,
    }
  }
}
Run Code Online (Sandbox Code Playgroud)