I have a basic struct called Frame
that is useful for a bunch of calculations:.
pub struct Frame<T> {
grid_val: Vec<T>,
grid_space: Vec<[T; 2]>,
calculated_result: Option<Vec<T>>
}
Frame
can be used to describe most basic calculations, but sometimes there's more complicated issues that come up and I need to add some more geometric information. So I used composition for each geometry:
pub struct Sphere<T> {
grid: Frame<T>,
radius: T
}
pub struct Hyperbola<T> {
top_grid: Frame<T>,
bottom_grid: Frame<T>,
internal_angle: T
}
Now I have a working implementation of Algorithm
for Sphere
:
pub trait Algorithm<T> {
fn calculate_something(&self) -> Result<Sphere<T>, Error>
}
impl Algorithm<T> for Hyperbola {
// do things with top_grid, bottom_grid, and internal_angle
}
impl Algorithm<T> for Sphere {
// do things with grid and radius
}
This fills in calculated_result
and returns a new Sphere
. It's implemented this way because Algorithm
needs to use the extra geometric information to compute the calculated_result
— semantically, it makes more sense for it to be an implementation on the geometry, whose result happens to be associated with one or more Frame
s.
I want to implement the same Algorithm
for Hyperbola
. In fact, it's very close to the same, and it makes sense for the trait to be the same, but it doesn't make sense for it to return a Sphere<T>
.
I know that I could add another trait like GeometricObject
and add another layer of composition, but that seems excessive. I guess I could maybe use a Box
, but that seems clumsy.
I also thought of having calculate_something
return a Vec<T>
to be inserted manually into whichever struct is in use, but then the ergonomics of returning the same struct type the method is called on are ruined (which is a waste in a public impl/trait).
How can I get this organized without making it traits all the way down?