rust - 如何在 Rust 中编写共享行为而不在每个模块中重复相同的代码?

标签 rust functional-programming shared behavior paradigms

对于编写一个非常大的程序,我认为没有办法减轻必须为每个使用某种共享行为的结构编写相同的代码。
例如,Dog 可能会“吠叫”:

struct Dog {
    is_barking: bool,
    ....
}
impl Dog {
    pub fn bark(self) {
        self.is_barking = true;
        emit_sound("b");
        emit_sound("a");
        emit_sound("r");
        emit_sound("k");
        self.is_barking = false;
    }
    ....
}
这种狗的许多品种可能存在:
struct Poodle {
    unique_poodle_val: &str
}
impl Poodle {
    pub fn unique_behaviour(self) {
        self.some_behaviour();
    }
}

struct Rottweiler {
    unique_rottweiler_val: u32
}
impl Rottweiler{
    pub fn unique_behaviour(self) {
        self.some_behaviour();
    }
}
问题是,以我目前的知识,Rust 似乎无法做到这一点,但它需要完成,我需要一个解决方法:
  • 允许 Poodle 和罗威纳犬使用该品种不需要考虑的完全相同的行为吠叫。
  • 无需在每个品种模块中重新编码 bark() 就可以实现这一点,这是编程 hell ,因为它会导致重复的代码,并且每个模块都必须实现 bark()。
  • Traits 是相反的,不能访问结构体,因此 default-trait 实现不起作用。 Rust 不支持类似 OOP 的继承,这里也不需要它。

  • 因此,我问:
    既然 Poodle 和罗威纳犬的吠叫方式完全相同,那么如何在不重写每个模块中的 bark() 的情况下实现 bark() 呢?
    请提供一个如何在 Rust 代码中解决这个问题的例子,欢迎使用惯用的和稍微有点 hacky 的解决方案,但请说明它们是什么,因为我仍在学习 Rust。
    谢谢你。

    编辑: bool 值不是线程的东西,而是在做某事之前设置一些状态的一个例子,即emit_sound 在这个状态内。我们放入 bark() 的任何代码都有同样的问题。对结构变量的访问是不可能的,比如特征。

    最佳答案

    你已经指出了 Rust 今天做得不好的事情:简洁地将基于内部数据和函数的行为添加到结构中。
    最典型的解决方法可能是将 Barking 隔离在所有狗拥有的结构中(如有疑问,更喜欢组合而不是继承):

    pub struct Barking {
        is_barking: bool,
    }
    impl Barking {
        pub fn do_it(&mut self) {
            self.is_barking = true; // <- this makes no sense in rust, due to the ownership model
            println!("bark");
            println!("a");
            println!("r");
            println!("k");
            self.is_barking = false;
        }
    }
    
    struct Poodle {
        unique_poodle_val: String,
        barking: Barking,
    }
    impl Poodle {
        pub fn unique_behaviour(self) {
            println!("some_behaviour");
        }
        pub fn bark(&mut self) {
            self.barking.do_it();
        }
    }
    
    struct Rottweiler {
        unique_rottweiler_val: u32,
        barking: Barking,
    }
    impl Rottweiler{
        pub fn unique_behaviour(self) {
            println!("unique behavior");
        }
        pub fn bark(&mut self) {
            // maybe decide to bite instead
            self.barking.do_it();
        }
    }
    
    在某些情况下,定义一个 Barking trait 是有意义的,它有一个通用的实现并声明一些处理状态的函数:
    pub trait Barking {
        fn bark(&mut self) {
            self.set_barking(true);
            println!("bark");
            println!("a");
            println!("r");
            println!("k");
            self.set_barking(false);
        }
        fn set_barking(&mut self, b: bool);
    }
    
    struct Poodle {
        unique_poodle_val: String,
        is_barking: bool,
    }
    impl Poodle {
        pub fn unique_behaviour(self) {
            println!("some_behaviour");
        }
    }
    impl Barking for Poodle {
        fn set_barking(&mut self, b: bool) {
            self.is_barking = b;
        }
    }
    
    请注意,这种半 OOP 方法通常会变得过于复杂且不易维护(如 OOP 语言中的继承)。

    关于rust - 如何在 Rust 中编写共享行为而不在每个模块中重复相同的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68756315/

    相关文章:

    oop - 函数式编程是否被认为更多 "mathematical"?如果是这样,为什么?

    design-patterns - 双折功能图案

    java - 访问共享目录

    windows - 如何编译文档中的示例?

    rust - 匹配运算符的可能未初始化变量的借用

    javascript - 如何使用任意原型(prototype)制作可调用的 JS 对象?

    Python 保存到映射共享驱动器时出错

    testing - 使用 cfg 属性有条件地计算间接函数调用的最佳方法是什么?

    rust - "Popping"来自 HashSet 的值

    static - Cmake:链接共享库