1

このコードを機能させるにはどうすればよいですか?

私の知る限り、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
  }
}
4

1 に答える 1

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

acase classを別ので拡張することはできないことに注意してください。通常、 es をまったくcase class拡張するのは悪いスタイルと見なされます。case classこれを実装するには、おそらくmethodで抽象化するSuperClazz必要SuperClazzがあるため、traitまたは である必要がありabstract classます。

scala での動的ディスパッチのもう 1 つの一般的な代替手段は、パターン マッチです。

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

スーパークラスまたはトレイトがsealed(この場合はsealed abstract class SuperClazz()) の場合、このようなパターン マッチを実装するのが一般的です。シールされたスーパー クラスのオブジェクトを照合する場合、コンパイラは、照合時に実行時エラーが発生しないように、一致するすべての可能性がリストされていることを確認します。いくつかの可能性を指定するのを忘れると、コンパイラは警告を出します。

パターン マッチは複数の引数の動的ディスパッチでも機能しますが、ポリモーフィズムと比較すると、通常はより多くのボイラープレート コードを記述する必要があり、すべてのマッチ ケースを線形にテストしてunapply関数を呼び出すためのランタイム パフォーマンス コストが大きくなる可能性があります。

于 2016-02-27T00:24:46.423 に答える