“多态"的 Rust 特征的简单组织;返回 [英] Simple organization of Rust traits for "polymorphic" return
问题描述
我有一个名为 Frame
的基本结构,它对大量计算很有用:.
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
可以用来描述最基本的计算,但有时会出现更复杂的问题,我需要添加更多的几何信息.所以我对每个几何图形都使用了合成:
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
}
现在我有一个适用于 Sphere
的 Algorithm
的工作实现:
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
}
这会填充 calculated_result
并返回一个新的 Sphere
.以这种方式实现是因为 Algorithm
需要使用额外的几何信息来计算 calculated_result
— 从语义上讲,它是几何上的实现更有意义,其结果恰好与一个或多个 Frame
s 相关联.
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.
我想为 Hyperbola
实现相同的 Algorithm
.事实上,它非常接近相同,并且特征相同是有意义的,但它返回一个 Sphere<T>
是没有意义的.
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>
.
我知道我可以添加另一个特征,例如 GeometricObject
并添加另一个合成层,但这似乎太过分了.我想我也许可以使用 Box
,但这似乎很笨拙.
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.
我还想过让 calculate_something
返回一个 Vec
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?
推荐答案
看来你想要一个关联类型:
pub trait Algorithm<T> {
type Output;
fn calculate_something(&self) -> Result<Self::Output, Error>;
}
impl<T> Algorithm<T> for Sphere<T> {
type Output = Sphere<T>;
fn calculate_something(&self) -> Result<Self::Output, Error> {
unimplemented!()
}
}
impl<T> Algorithm<T> for Hyperbola<T> {
type Output = Hyperbola<T>;
fn calculate_something(&self) -> Result<Self::Output, Error> {
unimplemented!()
}
}
关联类型 在 Rust 编程语言.我强烈建议通读整本书,熟悉 Rust 提供的功能类型.
Associated types are described in detail in The Rust Programming Language. I highly recommend reading through the entire book to become acquainted with what types of features Rust has to offer.
另一种解决方案是在 trait 上定义另一个泛型类型:
An alternate solution is to define another generic type on the trait:
pub trait Algorithm<T, Out = Self> {
fn calculate_something(&self) -> Result<Out, Error>;
}
impl<T> Algorithm<T> for Sphere<T> {
fn calculate_something(&self) -> Result<Sphere<T>, Error> {
unimplemented!()
}
}
impl<T> Algorithm<T> for Hyperbola<T> {
fn calculate_something(&self) -> Result<Hyperbola<T>, Error> {
unimplemented!()
}
}
然后您需要决定何时使用关联类型与泛型类型比较合适?
这篇关于“多态"的 Rust 特征的简单组织;返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!