Path
参数可以立即转换为PathBuf
,但这似乎效率低下。必须有一些方法来保持Path
,对吗?
use std::fs::File;
use std::path::Path;
struct Foo {
a: Option<File>,
b: Option<File>,
}
struct FooBuilder<'a> {
a: Option<&'a Path>,
b: Option<&'a Path>
}
impl<'a> FooBuilder<'a> {
fn new() -> FooBuilder<'a> {
FooBuilder {
a: None,
b: None,
}
}
fn a<P: AsRef<Path>+'a>(&'a mut self, a: P) -> &mut FooBuilder<'a> {
self.a = Some(a.as_ref());
self
}
fn b<P: AsRef<Path>+'a>(&'a mut self, b: P) -> &mut FooBuilder<'a> {
self.b = Some(b.as_ref());
self
}
fn done(&self) -> Foo {
Foo {
a: match self.a {
Some(path) => Some(File::open(path).unwrap()),
None => None,
},
b: match self.b {
Some(path) => Some(File::open(path).unwrap()),
None => None,
}
}
}
}
fn main() {
let path1 = Path::new("1");
let path2 = Path::new("2");
let foo = FooBuilder::new().a(path1).b(path2).done();
}
答案 0 :(得分:1)
这有效:
use std::fs::File;
use std::path::Path;
struct Foo {
a: Option<File>,
}
struct FooBuilder<'a> {
a: Option<&'a Path>,
}
impl<'a> FooBuilder<'a> {
fn new() -> FooBuilder<'a> {
FooBuilder {
a: None,
}
}
fn a<P: ?Sized>(&mut self, a: &'a P) -> &mut FooBuilder<'a>
where P: AsRef<Path>
{
self.a = Some(a.as_ref());
self
}
fn build(&self) -> Foo {
Foo {
a: self.a.map(|path| File::open(path).unwrap()),
}
}
}
fn main() {
let path1 = Path::new("1");
let foo = FooBuilder::new().a(path1).build();
}
让我们关注a
方法:
fn a<P: ?Sized>(&mut self, a: &'a P) -> &mut FooBuilder<'a>
where P: AsRef<Path>
此方法接受引用到实现AsRef<Path>
的类型。这意味着我们可以获得与Path
的引用,其生命周期与参数相同。另一个更改是通过Sized
使?
绑定为类型的可选项。这意味着我们可以参考一些我们不知道它有多大的东西。这很好,因为我们知道引用本身有多大。
让我们将其与原始版本进行比较:
fn a<P: AsRef<Path>+'a>(&'a mut self, a: P) -> &mut FooBuilder<'a> {
self.a = Some(a.as_ref());
self
}
此处,a
参数按值传递到方法a
。当您调用as_ref
时,您隐式在引用上将其调用到方法调用的堆栈帧上的项目。引用项将在方法调用结束时被删除,这意味着引用将变为无效。这就是你得到error: `a` does not live long enough
错误背后的原因。
我还使用Option::map
来清理build
方法。我将其重命名为build
,因为构建器通常应该使用build
方法,除非使用更明显的动词(如open
)。< / p>