(使用 Rust 1.74.1)
我有这个设置:
struct DataA {
a: i32
}
struct DataB {
b: i32
}
enum Data {
TypeA(DataA),
TypeB(DataB),
// TypeC etc...
}
struct Struct {
field: i32,
// other fields
data: Data,
}
impl Struct {
fn foo(&mut self) -> i32 {
self.field += 5;
return 5;
}
}
我想为
bar()
实现一个方法(Struct
),将TypeA(DataA)
的a
设置为foo()
的返回值,并且如果Struct
.data
不执行任何操作不是 TypeA
。
最初,我尝试过
fn bar(&mut self) {
let Data::TypeA(data) = &mut self.data else {
return;
};
data.a = self.foo();
}
但这不起作用,因为我
cannot borrow `*self` as mutable more than once at a time
。
经过一番尝试,我发现了一个错误
let Data::TypeA(..) = self.data else {
return;
};
self.data = Data::TypeA(DataA{ a: self.foo() });
它可以工作,但冗长且麻烦(例如,向 DataA 添加更多字段)。
请注意,
foo()
永远不会改变Struct
的data
,并且必须在after检查类型是否匹配后运行。
有没有更好的方法可以在不更改设置的情况下编写此代码? 如果没有,最惯用的方法是什么?
请注意,
永远不会改变foo()
的Struct
,并且必须在检查类型是否匹配后运行。data
我认为这是主要问题。虽然你说 foo 从不这样做,但你的 API 并没有反映这一点。如果可以,编译器会让你这样做。
如果您将
field
封装在自己的数据类型中,并将 foo
函数移动到那里,那么您实际上告诉编译器您只在此函数中修改 field
。
struct DataA {
a: i32,
}
struct DataB {
b: i32,
}
enum Data {
TypeA(DataA),
TypeB(DataB),
// TypeC etc...
}
struct FieldData {
field: i32,
}
impl FieldData {
fn foo(&mut self) -> i32 {
self.field += 5;
return 5;
}
}
struct Struct {
field: FieldData,
// other fields
data: Data,
}
impl Struct {
fn bar(&mut self) {
if let Data::TypeA(data) = &mut self.data {
data.a = self.field.foo();
}
}
}
像这样将一个结构体拆分为多个部分是解决此类问题的一个非常常见的解决方案。