“多态"的 Rust 特征的简单组织;返回 [英] Simple organization of Rust traits for "polymorphic" return

查看:23
本文介绍了“多态"的 Rust 特征的简单组织;返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 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
}

现在我有一个适用于 SphereAlgorithm 的工作实现:

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

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 Frames.

我想为 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 以手动插入到正在使用的任何结构中,但随后返回相同结构类型的人体工程学调用的方法被破坏了(这在公共 impl/trait 中是一种浪费).

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆