使用参数化函数

时间:2016-02-26 23:52:27

标签: scala types type-inference dynamic-dispatch multiple-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
  }
}

1 个答案:

答案 0 :(得分:4)

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

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()

请注意,您无法将case class扩展为另一个case class,而且通常会将case class扩展为method。要实现这一点,您可能需要在SuperClazz中将SuperClazz抽象为摘要,因此trait应为abstract classsealed 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) }

scala中动态分派的另一种常见替代方法是模式匹配:

sealed abstract class SuperClazz()

当超类或特征为sealed(在本例中为unapply)时,通常会实现这样的模式匹配。当匹配密封超类的对象时,编译器将检查您是否列出了匹配中的所有可能性,以确保匹配时不会出现运行时错误。如果您忘记指定一些可能性,编译器会给您一个警告。

模式匹配也适用于多参数动态调度,但与多态相比,它们通常需要编写更多的样板代码,并且可能需要更高的运行时性能成本来线性测试每个匹配大小写并调用double* ptr; ptr = (double*)malloc(10*_R_CONST*sizeof(double)+2048); 函数。