如何仅将某些结构成员设置为其默认值?
How can I set only some struct members to their default values?
我有结构 B
:
struct A {}
struct B {
a: A,
b: u32,
c: i8,
z: usize,
}
A
没有 Default
实现,也没有有意义的默认值。字段 b
..z
都需要初始化为默认值(在本例中为 0),并且 A
将被初始化为某个运行时值:
let b = B {
a: some_a(),
b: 0,
c: 0,
z: 0,
};
这并不理想。
更糟糕的是,如果要将 aa
添加到结构中,则需要将另一个成员添加到初始化程序中。使用 ..Default::default()
不起作用,因为 B
没有 Default
实现,因为默认值中的任何 A
都太昂贵而无法计算,以至于事后简单地丢弃.此外,无论如何,我都需要在 Default
实现中使用一个非常长的结构初始化器。
有没有什么方法可以将剩余的结构成员设置为它们的默认值(这样 b
将设置为默认值 u32
)而不用写出所有成员名称?
最好在添加新成员时对结构初始化程序进行最少的更改。这意味着这并不理想:
let b = B {
a: some_a(),
b: Default::default(),
c: Default::default(),
z: Default::default(),
};
如果您有大型结构,可以通过派生构建器或构造函数让您的生活更轻松。有几个板条箱可以做到这一点,一个流行的是 derive_builder
.
使用那个箱子,你可以做类似的事情:
use derive_builder::Builder;
// this derive will generate a struct called BBuilder
#[derive(Builder)]
struct B {
a: A,
#[builder(default = "0")]
b: u32,
#[builder(default = "0")]
c: i8,
/* ... */
#[default(default = "0")]
z: usize
}
fn main() {
let a = A { ... };
// all default values for fields b..z
let b = BBuilder::default().a(a).build().unwrap();
// or specify just some of the fields
let b = BBuilder::default()
.a(a)
.c(42)
.z(255)
.build()
.unwrap();
}
向 B
添加新字段不会影响使用 BBuilder
的代码,只要这些字段具有默认值即可。缺点是如果您错过必填字段而不是编译错误,您会遇到运行时恐慌。
另一个crate是derive-new
,比较简单。你会像这样使用它:
use derive_new::new;
#[derive(new)]
struct B {
a: A,
#[new(default)]
b: u32,
#[new(default)]
c: i8,
/* ... */
#[new(default)]
z: usize
}
fn main() {
let a = A { ... };
// all default values for fields b..z
let b = B::new(a);
// To specify some of the default fields, you need to mutate
let mut b = B::new(a);
b.c = 42;
b.z = 255;
}
这不会生成任何额外的结构,它只是添加了一个 new
方法,该方法接受所有非默认参数。如果您遗漏了任何非默认字段,则会出现编译错误。
我有结构 B
:
struct A {}
struct B {
a: A,
b: u32,
c: i8,
z: usize,
}
A
没有 Default
实现,也没有有意义的默认值。字段 b
..z
都需要初始化为默认值(在本例中为 0),并且 A
将被初始化为某个运行时值:
let b = B {
a: some_a(),
b: 0,
c: 0,
z: 0,
};
这并不理想。
更糟糕的是,如果要将 aa
添加到结构中,则需要将另一个成员添加到初始化程序中。使用 ..Default::default()
不起作用,因为 B
没有 Default
实现,因为默认值中的任何 A
都太昂贵而无法计算,以至于事后简单地丢弃.此外,无论如何,我都需要在 Default
实现中使用一个非常长的结构初始化器。
有没有什么方法可以将剩余的结构成员设置为它们的默认值(这样 b
将设置为默认值 u32
)而不用写出所有成员名称?
最好在添加新成员时对结构初始化程序进行最少的更改。这意味着这并不理想:
let b = B {
a: some_a(),
b: Default::default(),
c: Default::default(),
z: Default::default(),
};
如果您有大型结构,可以通过派生构建器或构造函数让您的生活更轻松。有几个板条箱可以做到这一点,一个流行的是 derive_builder
.
使用那个箱子,你可以做类似的事情:
use derive_builder::Builder;
// this derive will generate a struct called BBuilder
#[derive(Builder)]
struct B {
a: A,
#[builder(default = "0")]
b: u32,
#[builder(default = "0")]
c: i8,
/* ... */
#[default(default = "0")]
z: usize
}
fn main() {
let a = A { ... };
// all default values for fields b..z
let b = BBuilder::default().a(a).build().unwrap();
// or specify just some of the fields
let b = BBuilder::default()
.a(a)
.c(42)
.z(255)
.build()
.unwrap();
}
向 B
添加新字段不会影响使用 BBuilder
的代码,只要这些字段具有默认值即可。缺点是如果您错过必填字段而不是编译错误,您会遇到运行时恐慌。
另一个crate是derive-new
,比较简单。你会像这样使用它:
use derive_new::new;
#[derive(new)]
struct B {
a: A,
#[new(default)]
b: u32,
#[new(default)]
c: i8,
/* ... */
#[new(default)]
z: usize
}
fn main() {
let a = A { ... };
// all default values for fields b..z
let b = B::new(a);
// To specify some of the default fields, you need to mutate
let mut b = B::new(a);
b.c = 42;
b.z = 255;
}
这不会生成任何额外的结构,它只是添加了一个 new
方法,该方法接受所有非默认参数。如果您遗漏了任何非默认字段,则会出现编译错误。