2016-05-31 64 views
0

我有許多包含Builder結構的結構體。這些包裝提供了這個Builder的專門行爲。在這些包裝器之間轉換應該很容易,因爲它們本質上只是具有專門方法的Builder。我寫了一些代碼來說明 - 對於簡單的東西來說,它似乎有很多樣板。有沒有更好的辦法?有沒有更好的方法來使用From和Into來共享公共內部域的結構

struct Builder; 

trait ObjectBuilder: Into<Builder> + From<Builder> { 
    fn from_other<T: ObjectBuilder>(x: T) -> Self { 
    let builder = x.into(); 
    builder.into() 
    } 
} 

struct OtherBuilder { 
    inner: Builder 
} 

impl From<Builder> for OtherBuilder { 
    fn from(x: Builder) -> OtherBuilder { 
     OtherBuilder { 
      inner: x 
     } 
    } 
} 

impl Into<Builder> for OtherBuilder { 
    fn into(self) -> Builder { 
     self.inner 
    } 
} 

struct OtherOtherBuilder { 
    inner: Builder 
} 

impl From<Builder> for OtherOtherBuilder { 
    fn from(x: Builder) -> OtherOtherBuilder { 
     OtherOtherBuilder { 
      inner: x 
     } 
    } 
} 

impl Into<Builder> for OtherOtherBuilder { 
    fn into(self) -> Builder { 
     self.inner 
    } 
} 

impl ObjectBuilder for OtherBuilder {} 
impl ObjectBuilder for OtherOtherBuilder {} 

fn main() { 
    let x = Builder; 
    let y: OtherBuilder = x.into(); 
    let z: OtherOtherBuilder = ObjectBuilder::from_other(y); 
    let y = OtherBuilder::from_other(z); 
} 

Playground URL

Gist URL

+2

您可以使用[newtype_derive](https://danielkeep.github.io/rust-custom-derive/doc/newtype_derive/index .html)條目,但只適用於元組結構,即'struct OtherBuilder(Builder)'。 – kennytm

回答

2

而不是定義的包裝結構,你可以定義擴展性狀Builder –即特質,只在Builder實施,其中規定,你可以與方法調用附加功能調用語法(builder.func()而不是func(builder))。然後,只能導入適當範圍內相關的特徵(如模塊範圍,功能範圍等)。

這種方法的一個缺點是,如果你有多個特徵提供具有相同名稱的方法,那麼用方法調用語法調用這些方法將是不明確的(如果在相關作用域中導入多個線程)編譯器不知道你指的是哪個特徵。當然,你可以通過使用正常函數語法(MyBuilderExt::func(builder))來消除這個調用的歧義,但那不太好。在這種情況下,封裝可能是更好的方法。

2

您可以通過使用宏減少代碼重複:

struct Builder; 

trait ObjectBuilder: Into<Builder> + From<Builder> { 
    fn from_other<T: ObjectBuilder>(x: T) -> Self { 
    let builder = x.into(); 
    builder.into() 
    } 
} 

macro_rules! builder { 
    ($name:ident) => { 
     struct $name { 
      inner: Builder 
     } 

     impl From<Builder> for $name { 
      fn from(x: Builder) -> $name { 
       $name { 
        inner: x 
       } 
      } 
     } 

     impl Into<Builder> for $name { 
      fn into(self) -> Builder { 
       self.inner 
      } 
     } 

     impl ObjectBuilder for $name {} 
    } 
} 

builder!(OtherBuilder); 
builder!(OtherOtherBuilder); 

fn main() { 
    let x = Builder; 
    let y: OtherBuilder = x.into(); 
    let z: OtherOtherBuilder = ObjectBuilder::from_other(y); 
    let y = OtherBuilder::from_other(z); 
} 
相關問題