修改结构体中一个字段的简单方法?

3

我有以下代码:

#[derive(Clone, Copy)]
struct Point {
    x: f64,
    y: f64,
    z: f64
}

impl Point {
    fn set_z(&self, val: f64) -> Point {
        Point{x: self.x, y: self.y, z: val}
    }
}

struct Boo {
    point: Point
}

impl Boo {
    fn point(&self) -> &Point { &self.point }
    fn set_point(&mut self, val: &Point) { self.point = *val; }
}

fn main() {
    let mut boo = Boo{point:Point{x: 0., y: 0., z: 0.}};
    let new_p = boo.point().set_z(17.);
    boo.set_point(&new_p);
}

实际上,我有很多像Boo这样的结构体,其中包含Point字段,通常我只需要更改其中一个字段。

因此,我可以

  1. Implement millions of methods like:

    impl Boo {
        fn set_x(&mut self, val: f64) { self.point.x = val; }
        fn set_y(&mut self, val: f64) { self.point.y = val; }
        //...
    }
    

    Which is too boring, and if have two, three fields like point1, point2 and so on I will be buried under tons of these methods.

  2. The method described at the top of the question looks nicer because I need only two methods per field, but I have to make modification in two steps: get point and set point.

所以对我来说,理想的方法应该是这样的:
boo.set_point(boo.point().set_z(17.));

但这是不可能的,因为要实现这个目标,我需要同时读取和写入引用。

我如何简化我的模块用户设置Point中仅有一个字段的操作?


感觉如果有很多类型需要做同样的事情,那么实际上应该有一个类型拥有许多实例。 - Shepmaster
你可以像这样更改 impl Point:impl Point { fn set_z(&self, val: f64) -> Point { Point{z: val, *self} } } - S.R
我认为在这个主题中,你可以编写自己的"derive"来为你实现"Boo"中的"set_x"和"set_z"函数。但是我只是一个初学者,无法给你提供示例。 - S.R
1个回答

5
为什么不将这些字段设为公开?
#[derive(Clone, Copy)]
struct Point {
    pub x: f64,
    pub y: f64,
    pub z: f64
}

struct Boo {
    pub point: Point
}

boo.point.z = 17.0;

封装是一件好事,通常你不希望每个人都能更改类型的内部字段。但只有在字段不能采用非法值 或者 其他值依赖于该字段(例如缓存)时才需要这样做。但如果不是这种情况 - 在您的示例中似乎不是 - 那么只需将这些字段标记为公共的即可。


你也可以将 point 设为公共的,但不包括 z,然后你就可以调用 boo.point.set_z(17.0) - Shepmaster
1
有没有一种方法可以保持 x、y、z 的私密性,但允许创建一个具有不同 x 值的副本? - Andy Hayden

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