I have a trait and a struct implementing that trait (a trait object). I'd like to allocate my trait objects on the heap and to have other structures refer to them.
Box field
trait Material {}
struct Iron {}
impl Material for Iron {}
// It works, but takes ownership of boxes.
struct Sphere {
radius: f64,
material: Box<dyn Material>,
}
This code works but I can't have two spheres sharing the same Material
, because the Box
owns the material and a sphere owns its Box
field.
Reference field
My next attempt is to use a normal reference instead of a Box
:
struct Sphere<'a> {
radius: f64,
material: &'a dyn Material,
}
This also works, but as far as I understand, my Material
s will be allocated on the stack instead of the heap. What if the Material
value is really big and I'd rather have it on the heap? This leads me to the next approach which does not compile:
Reference to a Box
struct Sphere<'a> {
radius: f64,
material: &'a Box<dyn Material>,
}
fn main() {
let m1 = &Box::new(Iron {});
let s1 = Sphere {
radius: 1.0,
material: m1,
};
assert_eq!(s1.radius, 1.0);
}
This gives me the following error:
error[E0308]: mismatched types
--> src/main.rs:16:19
|
16 | material: m1,
| ^^ expected trait Material, found struct `Iron`
|
= note: expected type `&std::boxed::Box<(dyn Material + 'static)>`
found type `&std::boxed::Box<Iron>`
I am not quite sure where 'static
comes from in that type and it looks like it confuses the type checker. Otherwise dyn Material
and Iron
can be unified as far as I can understand.