6

我有时会发现自己在 C# 中编写了部分实现的抽象类:

abstract public class Executor {
    abstract protected bool Before();
    abstract protected bool During();
    abstract protected bool After();
    protected bool Execute() {
         var success = false;
         if (Before()) {
              if (During()) {
                  if (After()) {
                        success = true;
                  }
              }
         }
         return success;
    }
}

尽管这种控制结构很聪明,但我如何用像 rust 这样的函数式语言来完成这个(部分共享实现)?

4

2 回答 2

7

在特征上使用默认方法是一种方法(并且将来可能/希望成为惯用的方法;直到最近,struct@Slartibartfast 演示的 -with-closures 方法是唯一真正有效的方法):

#[allow(default_methods)];

trait Executable {
   fn before(&self) -> bool;
   fn during(&self) -> bool;
   fn after(&self) -> bool; 

   fn execute(&self) -> bool {
      self.before() && self.during() && self.after()
   }
}

impl Executable for int {
   fn before(&self) -> bool { *self < 10 }
   fn during(&self) -> bool { *self < 5 }
   fn after(&self) -> bool { *self < 0 }

   // execute is automatically supplied, if it is not implemented here
}

请注意,目前有可能实现Executable覆盖execute(我已经打开了一个关于#[no_override]会禁用此功能的属性的问题)。

此外,默认方法是实验性的并且容易使编译器崩溃(是的,比 Rust 的其余部分更严重),但它们正在迅速改进。

于 2013-07-08T14:24:05.223 回答
2

我不在 rust 编译器的范围内,所以请原谅损坏的代码。

在功能方面,您可以创建一个包含三个函数并调用它们的结构

struct Execution {
    before: @fn() -> bool,
    during: @fn() -> bool,
    after: @fn() -> bool
}

fn execute (e: Execution) -> bool {
  ...
}

但是一旦你有一个函数作为第一类值,你可以传递一个布尔函数列表来检查而不是固定的三个,或者其他取决于你想要实现的东西。

在事物的生锈方面,您可以通过使用特征使其更加“面向对象”

trait Executable {
    fn execute(&self);
}

impl Execution {
    fn execute(&self) {
        ...
    }
}
于 2013-07-08T11:14:45.233 回答