Reputation: 495
Recently I've been working on learning advanced Rust. As part of that, I'm learning to use dynamic dispatch.
In my tinkering I've run across a bit of an issue. For some reason, I can't seem to access fields of structs which have been assigned to variables using Boxes and dynamic dispatch. For example,
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}
}
}
yields the error message "error[E0609]: no field val
on type Box<dyn S>
"
Is there any way to access such fields, or do I need to kluge together a workaround?
Upvotes: 4
Views: 1848
Reputation: 2592
It is easy to understand why this does not work if you understand what a trait object is. When a method returns a dyn Trait
it does not return an instance of any struct
. Instead it returns a lookup table, which tells the caller where to find its methods. So the caller can access methods without knowing anything about underlying struct
itself.
So if the caller does not have access to the struct
itself it's clear it cannot access its fields.
There are two ways to implement what you are trying to do:
enum
. If you know complete list of options that the method can return, it's the best and the most Rust'y solution.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,
}
}
}
Upvotes: 5