【问题标题】:Rust: how to reuse the implementations of getter and setter?Rust:如何重用 getter 和 setter 的实现?
【发布时间】:2021-05-26 03:03:47
【问题描述】:

由于Rust不支持继承,我们不能重用另一个struct的状态。

Head First Design Patterns为例,一个抽象的Duck类有一个属性FlyBehavior,它还提供gettersetter

abstract class Duck {
   private FlyBehavior flyBehavior;
   public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; }
   public FlyBehavior getFlyBehavior() { return this.flyBehavior; }
}

但是,在 Rust 中,我们无法编写默认实现以供重用。

trait Duck {
    fn get_fly_behavior(&self) -> &dyn FlyBehavior;
    fn set_fly_behavior(&mut self, fly_behavior: Box<dyn FlyBehavior>);
}

并且任何实现Duck 的结构都必须编写相同 gettersetter。那么,有没有什么惯用的方法可以在 Rust 中重用 gettersetter 的实现?

【问题讨论】:

  • 这并不能回答你的问题,但让我给你一个一般性的建议:不要试图将 OOP 设计模式应用于 Rust。它们中的大多数根本不映射到 Rust,并且在 Rust 中没有用。例如,getter/setter 对在大多数 Rust 代码中相当少见。我知道忘记东西很难,但是 Rust 思考问题的方式与 OOP 完全不同。如果你愿意,你可以在 Rust 论坛上解释你试图解决的一般问题,并询问如何用惯用的 Rust 解决它。我认为这可能比回答这个确切的问题更有帮助。
  • 另外,你几乎肯定希望FlyBehavior 成为一个枚举。让它成为一个 trait 几乎就像是故意模仿 OOP 到 Rust 的糟糕映射。 (请不要认为这句话不友好,对概念上的枚举使用动态调度在 Rust 中看起来非常奇怪。)

标签: rust code-reuse trait-objects


【解决方案1】:

您可以通过在要为其实现特征的结构中提供字段fly_behavior 来重用您发布的特征,如以下演示所确保的那样

trait FlyBehavior {
    fn fun(&self);
}

trait Duck {
    fn get_fly_behavior(&self) -> &dyn FlyBehavior;
    fn set_fly_behavior(&mut self, fly_behavior: Box<dyn FlyBehavior>);
}

struct Behavior1{}
struct Behavior2{}
struct DuckObject {
    fly_behavior: Box<dyn FlyBehavior>,
}
impl Duck for DuckObject {
    fn get_fly_behavior(&self) -> &dyn FlyBehavior{
        &*self.fly_behavior
    }
    fn set_fly_behavior(&mut self, fly_behavior: Box<dyn FlyBehavior>){
        self.fly_behavior=fly_behavior
    }
}
impl FlyBehavior for Behavior1{
    fn fun(&self) {
        println!("Behave1")
    }
}

impl FlyBehavior for Behavior2{
    fn fun(&self) {
        println!("Behave2")
    }
}
fn main() {
    let mut duck = DuckObject{ fly_behavior: Box::new(Behavior1{}) };
    duck.get_fly_behavior().fun();
    duck.set_fly_behavior(Box::new(Behavior2{}));
    duck.get_fly_behavior().fun();
}

The result

【讨论】:

  • 你可能不明白我的意思。现在每个实现Duck 的结构仍然必须编写相同的获取/设置代码。例如,如果DuckObject2 怎么办?然后impl Duck for DuckObject2重复你写的所有内容。
  • @chenzhongpu 我认为问题的重点是你不能重用这个特征或者你不能实现它。但如果你想避免重复,请使用过程宏。例如使用#[derive(std::fmt::Debug)] 所做的事情
  • 感谢您的提示。我认为编写设计模式(例如示例中的strategy)有点不方便,因为Rust 不支持继承。所以,我想知道 Rust 中这种情况的最佳实践是什么。
猜你喜欢
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多