如何解决带有私有字段的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 举报,一经查实,本站将立刻删除。