带有参数化函数的Scala动态调度

ped*_*o91 1 types scala type-inference multiple-dispatch dynamic-dispatch

怎么可能使这段代码工作?

据我所知,Scala 没有动态调度(类似于 Java)。是否可以以某种方式模拟动态调度?

或者最好的解决办法是什么?

object Tezt {

  case class SuperClazz()
  case class SubClazz1() extends SuperClazz
  case class SubClazz2() extends SuperClazz

  def method(obj: SubClazz1) = {
    // stuff
  }

  def method(obj: SubClazz2) = {
    // stuff
  }

  def func[T <: SuperClazz](obj: T) = {
    Tezt.method(obj) // Error: Cannot resolve method reference with such signature
  }
}
Run Code Online (Sandbox Code Playgroud)

Kol*_*mar 5

在单个参数上实现动态调度的标准方法是面向对象的多态:

abstract class SuperClazz() {
  def method(): ReturnType
}
case class SubClazz1() extends SuperClazz {
  def method() = {
    // stuff
  }
}
case class SubClazz2() extends SuperClazz {
  def method() = {
    // stuff
  }
}

// Alternatively just `def func(obj: SuperClazz) =` in this case
def func[T <: SuperClazz](obj: T) = 
  obj.method()
Run Code Online (Sandbox Code Playgroud)

请注意,您不能将 acase class与 another 一起扩展case class,并且完全扩展case classes通常被认为是一种糟糕的风格。要实现这一点,您可能需要method抽象 in SuperClazz,因此SuperClazz应该是 atrait或 an abstract class

Scala 中动态调度的另一个常见替代方案是模式匹配:

sealed abstract class SuperClazz()
case class SubClazz1() extends SuperClazz
case class SubClazz2() extends SuperClazz

def method(obj: SubClazz1) = {
  // stuff
}

def method(obj: SubClazz2) = {
  // stuff
}

def func(obj: SuperClazz) =
  obj match {
    case sc1: SubClazz1 => method(sc1)
    case sc2: SubClazz2 => method(sc2)
  }
Run Code Online (Sandbox Code Playgroud)

当超类或特征是时,实现这样的模式匹配是很常见的 sealed(在这种情况下sealed abstract class SuperClazz())。当匹配密封超类的对象时,编译器会检查你是否列出了匹配中的所有可能性,以确保匹配时不会出现运行时错误。如果您忘记指定某些可能性,编译器会向您发出警告。

模式匹配也适用于多参数动态分派,但与多态性相比,它们通常需要编写更多样板代码,并且在线性测试每个匹配案例和调用unapply函数时可能具有更高的运行时性能成本。