这让我感到惊讶,因为我认为一个常见的用例是初始化一个结构,并且该结构的某些成员将是私有的,因此您可以隐藏后面的实现细节和接口。
问题在于结构更新语法并不像您想象的那样。例如,the book显示以下代码:
let user2 = User {
email: String::from("[email protected]"),
username: String::from("anotherusername567"),
..user1
};
The ..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, // assigning private field
y: _tmp.y, // assigning private field
z: 1,
}
};
而不是预期的:
// NOT what happens
let p = {
let _tmp = Point::default();
p.z = 1; // no private assignment
_tmp
};
我在这里有什么选择?
The most idiomatic option is to provide a builder for Point
. That is also somewhat bulky1, so if you're looking for a simple solution, you could also use Point::default()
and set the z
attribute manually. The struct update syntax is incompatible with structs with private fields and just not useful for your type.
1
Though there are crates like derive_builder, typed-builder and builder-pattern that take some of the drudgery away.