2016-07-23 4 views
0

В приведенном ниже коде единственное отличие в реализации заключается в println!.Аналогичные реализации одного признака для многих структур

Похоже, что для меня не должно быть необходимости выписывать две совершенно разные реализации, однако я не нашел пути.

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}, 
      } 
     } 
    } 
} 

Когда реализации точно идентичны, я могу использовать макрос для реализации для обоих. т.е.

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

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

Однако я не смог найти ни одного примера «макро» обусловленность

ответ

1

Вы могли бы передать «условные» части ваших макросов в виде отдельных параметров. Вдоль линии:

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

спасибо. это кажется очень разумным. Я мог бы также добавить функцию печати в функцию Change Decision и вызвать ее. Это означало бы, что мне не нужно было добавлять новую черту для него, однако я не уверен, что несколько функций для одного признака - хорошая практика/легко читается – user3920439

Смежные вопросы