简单组织Rust traits以实现“多态”返回

5

我有一个基本的结构体名为Frame,它在许多计算中非常有用。

pub struct Frame<T> {
    grid_val: Vec<T>,
    grid_space: Vec<[T; 2]>,
    calculated_result: Option<Vec<T>>
}

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
}

现在我已经有了一个可用的实现,用于处理“Sphere”上的“Algorithm”:
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相关联。
我想为Hyperbola实现相同的Algorithm。实际上,它非常接近,并且使用相同的特性是有意义的,但是将其返回Sphere<T>是没有意义的。
我知道我可以添加另一个特性,比如GeometricObject,并添加另一层组合,但这似乎过于复杂。我想也许可以使用Box,但这看起来很笨拙。
我还考虑过让calculate_something返回一个Vec<T>,然后手动插入到正在使用的任何结构体中,但这样做会破坏方法调用时返回相同结构体类型的人体工程学(在公共impl/trait中这是浪费)。
如何在不使特性全部嵌套的情况下进行组织?
1个回答

9

看起来你想要一个相关类型:

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提供的各种功能类型。
另一种解决方案是在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!()
    }
}

你需要决定何时使用关联类型与泛型,可以参考这里的讨论。

太令人兴奋了!我之前没有准备好,所以并没有完全理解书中的那部分内容,但现在我有了一些不错的上下文。 - bright-star

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接