Scala:绑定时间

Scala: binding time

在策略模式中,实现如下:

object StrategyPattern {

  def add(a: Int, b: Int) = a + b
  def subtract(a: Int, b: Int) = a - b
  def multiply(a: Int, b: Int) = a * b

  def execute(callback:(Int, Int) => Int, x: Int, y: Int) = callback(x, y)

def main(args: Array[String]) {
  println("Add:      " + execute(add, 3, 4))
  println("Subtract: " + execute(subtract, 3, 4))
  println("Multiply: " + execute(multiply, 3, 4))
  }
}

我想知道(如果对绑定时间的 types/forms 有很好的参考,我想知道如何理解其他情况)如果方法 add, substract, and multiply 的绑定时间是"construction time"(如果我可以这么说的话),或在 runtime?

简单的答案是(对于具体的 classes)方法定义在编译时绑定到方法名称,就像它们在 Java 中一样。例如,您的 add 方法完全等同于此 Java 定义:

public int add(int a, int b) {
    return a + b;
}

非最终方法

如果您从调用站点的角度分析非最终方法的绑定时间,其中具体 class 静态未知,则方法名称将被视为具有运行时绑定到它的实现(由于 subclassing/overriding)。

动态类加载

简单的答案接近事实,但 JVM 中的动态 class 加载使事情变得有点复杂。由于动态 class 加载,方法定义在技术上在运行时绑定到完全限定名称(例如,my.pkg.StrategyPattern.add)。当然可以有一个 my.package.StrategyPattern 模块的替代实现,并在其中动态选择(通过加载相应的 class 文件)。

当然,这种区别只与包含StrategyPattern定义的编译单元之外的代码有关。在编译单元内,方法总是在编译时被认为是绑定的。

策略

既然你问的是策略模式,我猜你还有别的想法?如果你问你是否可以在运行时 "strategies" 中 select,你可以:

val op: (Int, Int) => Int = 
  if (args(0) == "+") add
  else if (args(0) == "-") subtract
  else multiply
execute(op, 3, 4)

在这种情况下,op 在运行时绑定到一个 "strategy" 函数,但 addsubtractmultiply 仍然绑定到它们在编译时的定义。

这些方法中的每一个在编译时也与匿名 Function2 class 相关联,并且适当的 class 在运行时根据条件表达式的结果。这个细节实际上与绑定时间分析无关,因为 addsubtractmultiply 标识符的含义在编译时是固定的。