Last active
March 6, 2021 19:05
-
-
Save qnighy/e7a833eebd57ef778eaff3a8ab3649d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// この方法ならunwrap()もしなくてすむのではなかろうか | |
#[derive(Debug)] | |
struct Person { | |
id: u32, | |
name: String, | |
age: u32, | |
address: Option<String>, | |
zipcode: Option<String>, | |
} | |
// 例えばIdTypeは、未初期化なら(), 初期化済ならu32という型をもつ。 | |
// もし、IdTypeとしてBox<&[u8]>みたいなデタラメな型も入れられるのが | |
// 嫌なら、Empty/Filledというダミー型と適当なtraitを用意して、 | |
// Empty/Filledに対応するtrait implのassociated typeから型を | |
// 選択するという仕様にもできそう。 | |
#[derive(Debug)] | |
struct PersonBuilder<IdType, NameType, AgeType> { | |
id: IdType, | |
name: NameType, | |
age: AgeType, | |
address: Option<String>, | |
zipcode: Option<String>, | |
} | |
impl PersonBuilder<(), (), ()> { | |
pub fn new() -> Self { | |
PersonBuilder { | |
id: (), | |
name: (), | |
age: (), | |
address: None, | |
zipcode: None, | |
} | |
} | |
} | |
// PersonBuilder<u32, String, u32> は実はPersonと同型なんでPersonをtype synonymとする手もある | |
impl PersonBuilder<u32, String, u32> { | |
pub fn build(self) -> Person { | |
Person { | |
id: self.id, | |
name: self.name, | |
age: self.age, | |
address: self.address, | |
zipcode: self.zipcode, | |
} | |
} | |
} | |
// このimpl内で実装するとidなりnameなりは2回以上呼べるけど、ちょうど1回しか呼べない仕様にもできるはず | |
impl<IdType, NameType, AgeType> PersonBuilder<IdType, NameType, AgeType> { | |
pub fn id(self, id: u32) -> PersonBuilder<u32, NameType, AgeType> { | |
PersonBuilder { | |
id: id, | |
name: self.name, | |
age: self.age, | |
address: self.address, | |
zipcode: self.zipcode, | |
} | |
} | |
pub fn name<S: Into<String>>(self, name: S) -> PersonBuilder<IdType, String, AgeType> { | |
PersonBuilder { | |
id: self.id, | |
name: name.into(), | |
age: self.age, | |
address: self.address, | |
zipcode: self.zipcode, | |
} | |
} | |
pub fn age(self, age: u32) -> PersonBuilder<IdType, NameType, u32> { | |
PersonBuilder { | |
id: self.id, | |
name: self.name, | |
age: age, | |
address: self.address, | |
zipcode: self.zipcode, | |
} | |
} | |
pub fn address<S: Into<String>>(mut self, address: S) -> Self { | |
self.address = Some(address.into()); | |
self | |
} | |
pub fn zipcode<S: Into<String>>(mut self, zipcode: S) -> Self { | |
self.zipcode = Some(zipcode.into()); | |
self | |
} | |
} | |
fn main() { | |
let b = PersonBuilder::new() | |
.id(123) | |
.name("hoge") | |
.age(23) | |
.address("foo") | |
.build(); | |
println!("b = {:?}", b); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment