微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有私有字段的Rust impl默认特征

如何解决带有私有字段的Rust impl默认特征

进行这种设置时出现错误

default_test.rs:

mod default_mod;

use default_mod::Point;

fn main() {
  let _p1 = Point::new();
  let _p2: Point = Point {
    z: 1,..Default::default()
  };

}

default_mod.rs:

pub struct Point {
  x: i32,y: i32,pub z: i32,}

impl Point {
  pub fn new() -> Self {
      Point {
          x: 0,y: 0,z: 0,}
  }
}

impl Default for Point {
  fn default() -> Self {
      Point {
          x: 0,}
  }
}

这会导致编译器错误

default_test.rs:9:7
  |
9 |     ..Default::default()
  |       ^^^^^^^^^^^^^^^^^^ field `x` is private

error[E0451]: field `y` of struct `default_mod::Point` is private

简短版本-我有一个同时包含公共字段和私有字段的结构。我想使用认值初始化此结构,但有时会覆盖它们。

我似乎无法解决错误,也看不到互联网或文档中甚至提及此类错误的任何内容

这让我感到惊讶,因为我认为常见的用例是初始化一个结构,并且该结构的某些成员是私有的,因此您可以将实现细节隐藏在接口后面。

在我的情况下,私有字段是一个vec,因为我需要一些逻辑来添加删除向量中的内容,因此我想使其私有化,以防止任何人弄乱数据结构。

在这里有什么选择?

解决方法

这让我感到惊讶,因为我认为常见的用例是初始化一个结构,并且该结构的某些成员是私有的,因此您可以将实现细节隐藏在接口后面。

问题在于struct update语法无法实现您认为的功能。例如,the book显示以下代码:

let user2 = User {
    email: String::from("another@example.com"),username: String::from("anotherusername567"),..user1
};

..user1语法填充了我们尚未明确指定的User字段,例如active: user1.active,signin_count: user1.signin_count..后面可以跟一个任意表达式,该表达式返回Default::default()起作用的结构,并且其含义与User::default()相同,因为期望使用User。但是,退市仍然保持不变,归结为分配单个字段,在任何情况下都不授予对私有字段的特殊访问权限。

回到您的示例,此代码:

let p = Point {
    z: 1,..Default::default()
};

是以下语言的语法糖:

let p = {
    let _tmp = Point::default();
    Point {
        x: _tmp.x,y: _tmp.y,z: 1,};
};

而不是预期的:

// NOT what happens
let p = {
    let _tmp = Point::default();
    p.z = 1;
    _tmp
};

我在这里有什么选择?

最惯用的方法是为Point提供一个builder。这也有点笨重,因此,如果您正在寻找一个简单的解决方案,则还可以使用Point::default()并手动设置z属性。 struct update语法与带有私有字段的结构不兼容,只是对您的类型没有用。

,

我在这里有什么选择?

带有参数或构建器的new()

..struct只是进行功能更新的一种简便方法,它不会绕过ACL。在这里,由于您的结构具有私有字段,因此用户 不能将其作为“裸露”结构进行操作,因此必须将其视为很大程度上不透明的类型。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。