如何避免具有语义相等的字段/属性的不同结构的代码重复? [英] How to avoid code duplication of different structs with semantically equal fields/properties?

查看:130
本文介绍了如何避免具有语义相等的字段/属性的不同结构的代码重复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下两个结构:

pub struct RectangleRenderer {
    canvas: Canvas,
    origin: Point,
    shape: Rectangle,
}

pub struct CircleRenderer {
    canvas: Canvas,
    center: Point,
    shape: Circle,
}

当我来自Java时,我将从其中提取基类ShapeRenderer并将字段canvasorigin应用于其中,而特定类型将其字段称为shape.在这种情况下,Rust的最佳实践是什么,因为特征仅起到类似于界面的作用,因此不允许属性/字段?

As I come from Java, I would extract a base class ShapeRenderer out of those and apply the fields canvas and origin into that while the specific types will keep their field called shape. What's the best practice in Rust for this situation since traits only act similar to interfaces and therefore do not allow properties/fields?

推荐答案

对于您可以像这样制作单个结构:

You can make a single struct like this:

struct ShapeRenderer<T: Shape> {
    canvas: Canvas,
    origin: Point,
    shape: T,
}

请注意,我已经用特质Shape(必须创建)限制了通用类型T.您可以在此处放置任何喜欢的边界(或完全没有边界),但仅限于使用这些特征的成员.

Note that I have bounded the generic type T by a trait Shape (that you would have to create). You can put any bounds here you like (or no bounds at all), but you will be restricted to using members of those traits.

您想要通过形状访问的所有内容都需要通过Shape公开.例如,如果需要中心和区域,则特征定义可能如下所示:

Anything that you want to be able to access in your shapes would need to be exposed by Shape. For example, if you need the center and area, then the trait definition might look like this:

trait Shape {
    fn center(&self) -> (f64, f64);
    fn area(&self) -> f64;
}

如果这还不够灵活,还可以为ShapeRenderer仅针对特定形状提供特殊行为.例如:

If that is not enough flexibility, you could also give ShapeRenderer special behavior for only specific shapes. For example:

impl ShapeRenderer<Rectangle> {
    fn n_sides(&self) -> u32 {
        4
    }
}

请注意,在此impl中,我们可以访问Rectangle的所有字段,而不仅是Shape中的函数.

Note that inside this impl, we have access to all the fields of Rectangle, not just the functions in Shape.

或者,您可以创建一个基础结构,然后将其作为最终结构的成员:

Alternatively, you could create a base struct and then include it as a member of your final structs:

struct Renderer {
    canvas: Canvas,
    origin: Point,
}

struct CircleRenderer {
    renderer: Renderer,
    shape: Circle,
}

struct RectangleRenderer {
    renderer: Renderer,
    shape: Rectangle,
}

这是Rust中最接近标准继承的东西.

This is the closest thing in Rust to standard inheritance.

第三,如果您仅在创建这些结构时只关心代码重复,并且不希望它们共享字段以外的任何内容,则可以使用宏:

Thirdly, if you only care about code duplication when creating these structs and don't want them to share anything but fields, you could use a macro:

macro_rules! make_renderer {
    ($name: ty, $shape: ty) => (
        struct $name {
            canvas: Canvas,
            origin: Point,
            shape: $shape,
        }
    );
}

make_renderer!(CircleRenderer, Circle);
make_renderer!(RectangleRenderer, Rectangle);


虽然泛型示例最复杂,但它也是最强大和灵活的.它可以让您轻松地在结构之间共享代码,同时还可以让您拥有特定于某个代码的代码,从而可以访问其所有字段.


While the generics example is the most complicated, it is also the most powerful and flexible. It lets you easily have code shared between your structs, while also letting you have code specific to one that gives you access to all its fields.

这篇关于如何避免具有语义相等的字段/属性的不同结构的代码重复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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