(使用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;
}
}
字符串
我想为Struct
实现一个方法(bar()
),该方法将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
*selfas 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
,并且必须在检查类型是否匹配之后运行。
有没有更好的方法在不改变设置的情况下编写此代码?如果没有,最惯用的方法是什么?
1条答案
按热度按时间s5a0g9ez1#
请注意,
foo()
永远不会改变Struct
的data
,并且必须在检查类型是否匹配后运行。我认为这是主要的问题。虽然你说
foo
从来没有这样做过,但你的API并没有反映这一点。如果是这样,编译器会让你这样做。如果您将
field
封装在它自己的数据类型中,并将foo
函数移到那里,您实际上告诉编译器您只在此函数中修改field
。字符串
将一个结构体拆分成多个部分是解决此类问题的一个非常常见的解决方案。
如果你需要对结构体的其他部分进行只读访问,比如前面的
DataA
对象,你可以通过函数参数传入它:型