4

与えられたクラス

sealed abstract class A

case class B(param: String) extends A

case class C(param: Int) extends A

trait Z {}

class Z1 extends Z {}

class Z2 extends Z {}

def zFor[T <: A : Manifest]: Option[Z] = {
  val z = manifest[T].erasure
  if (z == classOf[B]) {
    Some(new Z1)
  } else
  if (z == classOf[C]) {
    Some(new Z2)
  } else {
    None
  }
}

ここでのパターン マッチングの問題は、バイトコードでパターン マッチング テーブルを作成できないことだと思います。この問題の回避策はありますか? コンパイラによってマニフェストで生成された Int を使用できますか?

4

2 に答える 2

1

これがあなたの問題に当てはまるかどうかはわかりません(おそらく単純化された例を示しているため)。しかし、この種の機能は、リフレクションを使用しなくても作成できます。

元のコードを変更せずに組み合わせを追加できる非常に一般的なパターンです。

// the - here allows D to return the instance for C
// if you only want exact matches, remove the -
trait GetZ[-X] {
  type Out
  def z: Option[Out]
}

trait LowerPriority {
  implicit def noZ[A] =
    new GetZ[A] {
      type Out = Nothing
      val z = None
    }
}

object GetZ extends LowerPriority {
  implicit def forB =
    new GetZ[B] {
      type Out = Z1
      def z = Some(new Z1)
    }

  implicit def forC =
    new GetZ[C] {
      type Out = Z2
      def z = Some(new Z2)
    }
}

def zFor[T](implicit getZ: GetZ[T]): Option[getZ.Out] = getZ.z

使用法

class D extends C(5)

val noZ = zFor[A]
val Some(z1) = zFor[B]
val Some(z2) = zFor[C]
val Some(other_z2) = zFor[D]
于 2014-10-21T21:38:28.313 に答える