多方法
注意: 从Nim 0.20开始,要使用多方法,必须在编译时明确传递 —multimethods:on 。
程序总是使用静态调度。多方法使用动态调度。 要使动态分派处理对象,它应该是引用类型。
- type
- Expression = ref object of RootObj ## abstract base class for an expression
- Literal = ref object of Expression
- x: int
- PlusExpr = ref object of Expression
- a, b: Expression
- method eval(e: Expression): int {.base.} =
- # 重写 base 方法
- raise newException(CatchableError, "Method without implementation override")
- method eval(e: Literal): int = return e.x
- method eval(e: PlusExpr): int =
- # 当心: 依赖动态绑定
- result = eval(e.a) + eval(e.b)
- proc newLit(x: int): Literal =
- new(result)
- result.x = x
- proc newPlus(a, b: Expression): PlusExpr =
- new(result)
- result.a = a
- result.b = b
- echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
在示例中,构造函数 newLit 和 newPlus 是procs因为它们应该使用静态绑定,但 eval 是一种方法,因为它需要动态绑定。
从示例中可以看出,基本方法必须使用 base 编译指示进行注释。 base 编译指示还可以提醒程序员使用基本方法 m 作为基础来确定调用 m 可能导致的所有效果。
注意: 编译期执行不支持方法。
注意: 从Nim 0.20开始,不推荐使用泛型方法。
通过procCall禁止动态方法解析
可以通过内置的 system.procCall 来禁止动态方法解析。 这有点类似于传统OOP语言提供的 super 关键字。
- type
- Thing = ref object of RootObj
- Unit = ref object of Thing
- x: int
- method m(a: Thing) {.base.} =
- echo "base"
- method m(a: Unit) =
- # Call the base method:
- procCall m(Thing(a))
- echo "1"