Reputation: 69
I am trying to create a static array of objects that implement a common trait. All these structs and their sizes are known at compile time. But when accessing a field defined on the struct the compiler tells me that the field is not on the type.
fn main() {
for &thing in ALL_THINGS {
println!("{}", thing.name)
}
}
trait Thing: Sync { }
struct SpecificThing {
name: &'static str
}
impl Thing for SpecificThing { }
static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}];
error[E0609]: no field `name` on type `&dyn Thing`
--> src/main.rs:3:30
|
3 | println!("{}", thing.name)
| ^^^^
The questions static array of trait objects, Create vector of objects implementing a trait in Rust, Can I have a static borrowed reference to a trait object? or Vector of objects belonging to a trait doesn't help with explaining why this happens or how to resolve it.
Please what am I doing wrong here? Is there a better method to solve this task that I have not found yet?
Upvotes: 3
Views: 1789
Reputation: 1637
When you define &dyn Thing
, you erase all the information about specific data type. That means you can't access fields of dinamically dispatched objects.
Just imagine that you have two different structs in ALL_THINGS
:
struct SpecificThing {
name: &'static str
}
struct SpecificAnotherThing {
no_name: &'static str
}
static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}, &SpecificAnotherThing { no_name: "" }];
You can't access name
field because trait Thing
know nothing about concrete types it implemented for. Therefore you can't access it's fields directly.
If you really need it, you should define a method in Thing
trait which will return value you need:
trait Thing: Sync {
fn name(&self) -> &str;
}
// ...
// ...
impl Thing for SpecificThing {
fn name(&self) -> &str {
self.name
}
}
Or you can use static dispatching and algebraic data types (enum
).
Upvotes: 3
Reputation: 2507
You can't access SpecificThing.name
from a &dyn Thing
since not all Things
have a name
field (ignoring the fact that traits don't have fields).
Your use of dyn Thing
suggests you have a set of objects (structs/enums) that have some things in common. All these commonalities must be present in Thing
for you to access them. For example, if a name is a common thing, you could add a function that gets the name:
fn main() {
for &thing in ALL_THINGS {
println!("{}", thing.get_name())
}
}
trait Thing: Sync {
fn get_name(&self) -> &'static str;
}
struct SpecificThing {
name: &'static str
}
impl Thing for SpecificThing {
fn get_name(&self) -> &'static str {
self.name
}
}
static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}];
Upvotes: 1