Rust特征的简单组织以实现“多态”返回

bri*_*tar 3 polymorphism traits rust

我有一个称为的基本结构Frame,可用于一堆计算:。

pub struct Frame<T> {
    grid_val: Vec<T>,
    grid_space: Vec<[T; 2]>,
    calculated_result: Option<Vec<T>>
}
Run Code Online (Sandbox Code Playgroud)

Frame可以用来描述大多数基本计算,但是有时会出现更复杂的问题,因此我需要添加一些更多的几何信息。所以我对每种几何使用了合成:

pub struct Sphere<T> {
    grid: Frame<T>,
    radius: T
}

pub struct Hyperbola<T> {
    top_grid: Frame<T>,
    bottom_grid: Frame<T>,
    internal_angle: T
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个工作实现AlgorithmSphere

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
}
Run Code Online (Sandbox Code Playgroud)

填写calculated_result并返回一个新的Sphere。之所以采用这种方式,是因为Algorithm需要使用额外的几何信息来计算calculated_result-从语义上来说,将其作为几何上的实现更为有意义,其结果恰好与一个或多个Frames 相关联。

我想为实现相同AlgorithmHyperbola。实际上,它非常接近相同,并且特征相同是有意义的,但是返回a却没有意义Sphere<T>

我知道我可以添加另一个特质,例如GeometricObject添加另一层构图,但这似乎过多。我想我可能可以使用Box,但这似乎很笨拙。

我还想到了将calculate_somethingreturn a Vec<T>手动插入到正在使用的任何struct中,但随后返回返回与调用该方法相同的struct类型的人机工程学就被破坏了(这在公共impl / trait中是一种浪费)。

我如何才能组织起来而又不至于使其特质下降呢?

She*_*ter 5

似乎您需要关联的类型

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!()
    }
}
Run Code Online (Sandbox Code Playgroud)

相关类型在Rust编程语言中进行了详细描述。我强烈建议您通读整本书,以熟悉Rust提供的功能类型。

另一种解决方案是在特征上定义另一个通用类型:

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!()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要确定何时使用关联类型与泛型类型比较合适?