2016-07-23 2 views
0

以下のコードでは実装の唯一の違いはprintln!です。多くの構造体の1つの特性の同様の実装

私は2つの全く異なる実装を書く必要がないように感じていますが、方法は見つけられません。

pub trait ChangeDecision{ 
    fn change_decision(&mut self); 
} 

impl ChangeDecision for Hero{ 
    fn change_decision(&mut self){ 
     self.should_change_decision = false; 
     let rand_num = rand::thread_rng().gen_range(1, 101) as f32/100.; 
     let mut prob_counter = 0.0; 
     for (action, prob) in &mut self.decisions.iter(){ 
      prob_counter += *prob; 
      match prob_counter{ 
       p if rand_num > p => {}, 
       _ => {println!("{}: {:?}", self.name, action); self.current_decision = *action; break}, 
      } 
     } 
    } 
} 

impl ChangeDecision for Team{ 
    fn change_decision(&mut self){ 
     self.should_change_decision = false; 
     let rand_num = rand::thread_rng().gen_range(1, 101) as f32/100.; 
     let mut prob_counter = 0.0; 
     for (action, prob) in &mut self.decisions.iter(){ 
      prob_counter += *prob; 
      match prob_counter{ 
       p if rand_num > p => {}, 
       _ => {println!("{:?}: {:?}", self.side, action); self.current_decision = *action; break}, 
      } 
     } 
    } 
} 

実装では、私は両方のために実装するためにマクロを使用することができ、正確に同一です。私は「マクロコンディショナリティー」

答えて

1

のいずれかの例を見つけることができませんでしたしかし、すなわち

macro_rules! impl_SimilarStuff { 
    ($T:ident) => { 
     impl SimilarStuff for $T{ 
      fn my_func(&mut self){ 
       true 
      } 
     } 
    } 
} 

impl_SimilarStuff!(ThingOne); 
impl_SimilarStuff!(ThingTwo); 

あなたは別々のパラメータとしてあなたのマクロに「条件付き」の部分を渡すことができます。線に沿って:

struct S1 {n1 : isize} 
struct S2 {n2 : isize} 

trait T { 
    fn print_me(self); 
} 

macro_rules! doit { 
    ($t: ty, $member: ident) => (
     impl T for $t { 
      fn print_me(self) { 
       println!("{}", self.$member); 
      } 
     } 
    ) 
} 

doit!(S1, n1); 
doit!(S2, n2); 

fn main() { 
    let s1 = S1 {n1: 1}; 
    let s2 = S2 {n2: 2}; 
    s1.print_me(); 
    s2.print_me(); 
} 

「カスタムパーツ」はいくつかの簡単な文よりも大きい場合は、@クリスエマーソンにより示唆されるように、自身の特性にカスタムパーツを抽出し検討することができます。

また、特性を満足させるものとカスタムパーツをクロージャとして使用して、汎用関数を記述することもできます。しかし、これはあなたの形質を変更することを伴うかもしれません。

+0

回答ありがとうございます。これを試してみます – user3920439

2

私がこれを扱う方法は、異なる部分を扱うために別の特性を使うことです。次のようなもの:

trait PrintSomething { 
    fn print_something(&self, action: Action); 
} 

impl PrintSomething for Hero { 
    fn print_something(&self, action: Action) { 
     println!("{}: {:?}", self.name, action); 
    } 
} 

impl PrintSomething for Team { 
    fn print_something(&self, action: Action) { 
     println!("{}: {:?}", self.side, action); 
    } 
} 

// Now the macro would expand to: 
impl ChangeDecision for Hero { 
    fn change_decision(&mut self){ 
     self.should_change_decision = false; 
     let rand_num = rand::thread_rng().gen_range(1, 101) as f32/100.; 
     let mut prob_counter = 0.0; 
     for (action, prob) in &mut self.decisions.iter(){ 
      prob_counter += *prob; 
      match prob_counter{ 
       p if rand_num > p => {}, 
       _ => { 
        self.print_something(action); 
        self.current_decision = *action; 
        break 
       }, 
      } 
     } 
    } 
} 
+0

ありがとうございます。これは非常に賢明なようです。 私はprint something関数をChange Decision特性に追加して呼び出すこともできます。 これは、私はそれのために新しい形質を追加する必要はありませんが、私は1つの形質の複数の機能が良い練習/読みやすい – user3920439

関連する問題