2015-12-08 67 views
1

考慮定義特徵RefGen,結構Facade的代碼,該結構具有可以容納RefGen的屬性和兩個不同的new_*方法,該方法將爲RefGen選擇不同的具體實現。我是否需要多個impl塊來實現爲類型參數設置具體類型的多個方法?

trait RefGen { 
    fn gen() -> String; 
} 

struct FooGen; 

impl RefGen for FooGen { 
    fn gen() -> String { 
     "foo".to_owned() 
    } 
} 

struct BarGen; 

impl RefGen for BarGen { 
    fn gen() -> String { 
     "bar".to_owned() 
    } 
} 

struct Facade<R: RefGen> { 
    gen: R 
} 

impl Facade<FooGen> { 
    fn new_foogen() -> Self { 
     Facade { 
      gen: FooGen 
     } 
    } 
} 

impl Facade<BarGen> { 
    fn new_bargen() -> Self { 
     Facade { 
      gen: BarGen 
     } 
    } 
} 

fn main() {} 

它的工作原理,但它令我感到困惑,我需要爲兩個impl塊?

+1

你能說明你打算如何使用你的Facade?我懷疑你正試圖獲得動態調度,並希望在這裏使用某種形式的特質對象。 –

+0

這可能只是一箇中間步驟,因爲設計目前處於早期設計階段。不過,我可以想象在外觀上有三種方法。 'new (ref_gen:R)'會讓用戶決定使用哪個'RefGen',而'new_with_foo'和'new_with_bar'會設置具體的'RefGen'實現。就我所知,沒有動態調度。 – Christoph

回答

4

如果您想爲每種類型命名方法,這是唯一的方法。如果你想一般做到這一點,你可以使用一個通用的IMPL:

impl<R: RefGen> Facade<R> { 
    fn new() -> Self { 
     Facade { 
      gen: R::new(), 
     } 
    } 
} 

當然這需要RefGen性狀提供某種new函數來創建實例:

trait RefGen { 
    fn gen() -> String; 
    fn new() -> Self where Self: Sized; 
} 

where Self: Sized界在那裏,所以特質仍然是對象安全的。這意味着您可以創建一個Box<RefGen>,但不能調用new方法。

雖然現在您不能在GenFooGenBar對象上調用gen方法,因爲它是一種靜態方法。您需要爲其添加&self參數。如果你永遠要真正創建GenFoo類型或GenBar的對象,因爲他們永遠不會有田,你完全可以通過在編譯時做的所有調度擺脫gen場和new構造:

struct Facade<R: RefGen> { 
    gen: PhantomData<R>, 
} 

impl<R: RefGen> Facade<R> { 
    fn new() -> Self { 
     Facade { 
      gen: PhantomData, 
     } 
    } 
    fn gen(&self) -> String { 
     R::gen() 
    } 
} 

impl Facade<FooGen> { 
    fn new_foogen() -> Self { 
     Self::new() 
    } 
} 

impl Facade<BarGen> { 
    fn new_bargen() -> Self { 
     Self::new() 
    } 
} 
相關問題