方法

过程总是静态派发,而方法则使用动态派发。为了将动态派发应用在对象上,对象必须是引用类型。

  1. type
  2. Expression = ref object of RootObj ## 表达式的抽象基类
  3. Literal = ref object of Expression
  4. x: int
  5. PlusExpr = ref object of Expression
  6. a, b: Expression
  7. method eval(e: Expression): int {.base.} =
  8. # 一定要重写这个基方法
  9. raise newException(CatchableError, "未重写基方法")
  10. method eval(e: Literal): int = return e.x
  11. method eval(e: PlusExpr): int =
  12. # 注意: 这里依赖于动态绑定
  13. result = eval(e.a) + eval(e.b)
  14. proc newLit(x: int): Literal =
  15. new(result)
  16. result.x = x
  17. proc newPlus(a, b: Expression): PlusExpr =
  18. new(result)
  19. result.a = a
  20. result.b = b
  21. echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))

在这个例子中,构造函数 newLit 和 newPlus 都是过程,因为它们都使用静态绑定,但是 eval 是方法因为需要动态绑定。

正如这个例子所示,基方法必须使用 base 编译指示修饰。base 编译指示对于开发者来说也是一种提醒: 这个基方法 m 是推断方法 m 所能产生的所有效果的一个基础。

注意: 目前还不支持方法的编译期执行。

注意: 从 Nim 0.20 开始,泛型方法已被弃用。