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

Posted

技术标签:

【中文标题】“多态”返回的 Rust 特征的简单组织【英文标题】:Simple organization of Rust traits for "polymorphic" return 【发布时间】:2017-05-12 03:34:17 【问题描述】:

我有一个名为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 — 从语义上讲,它是几何上的实现更有意义,其结果恰好与一个或多个@987654332 相关联@s.

我想为Hyperbola 实现相同的Algorithm。事实上,它非常接近相同,并且 trait 相同是有意义的,但它返回 Sphere&lt;T&gt; 是没有意义的。

我知道我可以添加另一个特征,例如 GeometricObject 并添加另一层构图,但这似乎太过分了。我想我可以使用Box,但这似乎很笨拙。

我还想过让 calculate_something 返回一个 Vec&lt;T&gt; 以手动插入到正在使用的任何结构中,但是返回调用该方法的相同结构类型的人体工程学被破坏了(这在公共 impl/trait)。

我怎样才能在不把它的特征完全降低的情况下把它组织起来?

【问题讨论】:

【参考方案1】:

看来你想要一个关联类型

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!()
    

The Rust Programming Language 中的关联类型 are described in detail。我强烈建议通读整本书以熟悉 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!()
    

然后你需要决定When is it appropriate to use an associated type versus a generic type?

【讨论】:

太令人兴奋了!我并没有真正理解这本书的那部分,因为我还没有准备好,但现在我有了一些很好的背景。

以上是关于“多态”返回的 Rust 特征的简单组织的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用多态时,“错误:结构定义中不允许使用特征边界”

如何从特征实现中返回HashMap的键上的迭代器?

Rust错误处理

返回使用 Rocket 和 Diesel (Rust) 在 PostgreSQL 中创建的单个记录

TJI读书笔记11-多态

为啥 Rust 在 main 函数中没有返回值,以及如何返回值?