2015-11-06 33 views
1

Path參數可以立即轉換爲PathBuf,但這似乎效率低下。必須有某種方法保持Path,對吧?如何編寫存儲`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

@Shepmaster可以直接在函數'a()'和'b()'創建文件,那麼你不需要保存路徑。但是這可能不是意識形態上的正確。作爲一個變體,仍然可以將'Option '設置爲該函數的參數,但會變得冗長。 (共4檔) – waxogi

+0

@Shepmaster這就是我尋求幫助的原因。如果他們是正常的參考 - 沒有問題的生活,但與'路徑'你只能通過'AsRef'工作。 – waxogi

回答

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)。