有时你会有这样的事情:
let mut something = Something::new();
something.set_property_a("foo");
something.set_property_b("bar");
let result = something.result();
你所需要的只是结果,但现在范围被something
污染了。
在Kotlin中,您可以这样做(在其他版本中,但为了清晰起见使用详细的):
val result = Something().let { x ->
x.propertyA = "foo"
x.propertyB = "bar"
x.result()
}
T.let(closure)
只运行闭包,将调用它的对象(Something
的实例)作为参数,并返回闭包返回的内容。非常轻巧,简单的概念,但非常有帮助。
在Rust中可以做类似的事吗?我最接近的是:
let result = {
let mut x = Something::new();
x.set_property_a("foo");
x.set_property_b("boo");
x.result()
};
答案 0 :(得分:2)
您可以使用builder pattern。这是Rust中用来实现你想要的东西的惯用方法:
#[derive(Debug)]
struct Something {
property_a: String,
property_b: String,
}
#[derive(Debug, Default)]
struct SomethingBuilder {
property_a: Option<String>,
property_b: String,
}
#[derive(Debug)]
enum BuildError {
ANotSet,
}
impl SomethingBuilder {
fn new() -> Self {
Self::default()
}
fn with_a(mut self, a: String) -> Self {
self.property_a = Some(a);
self
}
fn with_b(mut self, b: String) -> Self {
self.property_b = b;
self
}
fn build(self) -> Result<Something, BuildError> {
Ok(Something {
property_a: self.property_a.ok_or(BuildError::ANotSet)?,
property_b: self.property_b,
})
}
}
fn main() {
let thing = SomethingBuilder::new()
.with_a("foo".into())
.with_b("bar".into())
.build() // returns BuildError if set_a is left out
.unwrap();
println!("{:?}", thing);
}
例如,请参阅this real world usage。
在构建器结构中,您可以在调用build
方法时执行所需的所有验证。如果一切正常,您可以返回新构建的struct
。此模式的优点是代码的可读性(无“污染”)和保证构建的struct
完全有效的用户。