许多结构的一个特征的类似实现

时间:2016-07-23 11:13:42

标签: rust

在下面的代码中,实现中唯一不同的是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);

但是我找不到任何'宏观条件'的例子

2 个答案:

答案 0 :(得分: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
                 },
            }
        }
    }
}

答案 1 :(得分: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();
}

如果“自定义部分”比某些简单语句大,您可以考虑将自定义部分提取为自己的特征,如@Chris Emerson所建议。

或者,您可以尝试编写一个泛型函数,将满足您特征的内容和自定义部分作为闭包。但是,这可能涉及修改您的特质。