あなたがやろうとしていることは構造型付けと呼ばれ、Scala でサポートされています。実際のクラスがないため、JVM での実装はリフレクションに依存する必要がgetCあるため、特性ベースのソリューションと比較して呼び出しがかなり遅くなります。このような状況での呼び出しはリフレクション呼び出しと呼ばれ、自分が何をしているのかを知っていることを認識しgetCない限り、コンパイラは実際に警告を発します。import scala.language.reflectiveCalls
私の意見では、通常型クラスと呼ばれるものに依存する、より洗練されたソリューションがあります。HasC「持つ」とはどういう意味かを定義するトレイトを定義し、 とCの両方の実装を提供します。はあなたの特徴であるため、との実装を制御できなくても実行できます。次に、暗黙的に使用可能な任意の型を取る has を定義します。Scala はコンテキスト境界を通じてこれをサポートします: . ABHasCABreadCTHasC[T]def readC[T: HasC]
これが実際の例です:
class A {
def getCFromA: Int = 10
}
class B {
def getCFromB: Int = 100
}
trait HasC[T] {
def c(t: T): Int
}
object HasC {
implicit object AHasC extends HasC[A] {
def c(a: A): Int = a.getCFromA
}
implicit object BHasC extends HasC[B] {
def c(b: B): Int = b.getCFromB
}
}
def readC[T : HasC](t: T): Int = implicitly[HasC[T]].c(t)
val a = new A()
val b = new B()
readC(a)
readC(b)
この行
def readC[T : HasC](t: T): Int = implicitly[HasC[T]].c(t)
は、(ほぼ間違いなく)より優れた書き方です
def readC[T](t: T)(implicit hasC: HasC[T]): Int = hasC.c(t)
と の両方でgetC定義する必要がないため、これはより一般的であることに注意してください。そのため、メソッドの名前をおよびに変更しました。ABgetCFromAgetCFromB
型クラスは、Scala の多くの関数型プログラミングの基礎であり、同様の概念が Haskell、Rust (トレイト)、Swift (プロトコル) などの他の最新の言語で利用できます。