Reputation: 21746
I'm learning Rust and I'm having difficulties in implementing polymorphism. I want to use an array to store either Circle
or Test
.
trait Poli {
fn area(&self) -> f64;
}
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn new (xx: f64, yy: f64, r: f64) -> Circle{
Circle{ x: xx, y: yy, radius: r }
}
}
impl Poli for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct Test {
x: f64,
y: f64,
radius: f64,
test: f64,
}
impl Test {
fn new (xx: f64, yy: f64, r: f64, t: f64) -> Circle{
Test{ x: xx, y: yy, radius: r, test: t, }
}
}
impl Poli for Test {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
I do not know how to make a vector to store types with the same trait
:
let cir = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);
//let mut vec: Vec<Poli> = Vec::new(); <---
I'd like to iterate the vector and call functions from the trait. Is there any way to do this, or some alternative?
I read the trait object documentation but I think it's not what I want.
Upvotes: 2
Views: 493
Reputation: 21746
After Dogbert's response, I played a bit and found this way works for me. I am new to Rust and I do not know if this is obvious, but I'll leave it here to help others.
let circle = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);
let mut vec: Vec<&Poli> = Vec::<&Poli>::new();
vec.push(&circle);
vec.push(&test);
for v in vec {
println!("new {}", v.area());
}
Upvotes: 0
Reputation: 222398
As mentioned in the page you linked to, you'll need to either store the Poli
implementing structs as Vec<&Poli>
or Vec<Box<Poli>>
depending on whether you want to own the values or just store a reference:
// Owned
let circle = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);
let polis = vec![Box::new(circle) as Box<Poli>, Box::new(test) as Box<Poli>];
for poli in polis {
println!("{}", poli.area());
}
// Reference
let circle = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);
let polis = vec![&circle as &Poli, &test as &Poli];
for poli in polis {
println!("{}", poli.area());
}
Output
314.1592653589793
314.1592653589793
314.1592653589793
314.1592653589793
Upvotes: 6