【问题标题】:Simple organization of Rust traits for "polymorphic" return“多态”返回的 Rust 特征的简单组织
【发布时间】: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)。

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

【问题讨论】:

    标签: polymorphism rust traits


    【解决方案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?

    【讨论】:

    • 太令人兴奋了!我并没有真正理解这本书的那部分,因为我还没有准备好,但现在我有了一些很好的背景。
    猜你喜欢
    • 2020-12-31
    • 2022-07-31
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多