私は次のような状況で「より良い」(より慣用的な?) Scala コードを書こうとしています: 次のような参照ケース クラスの並列セットに属する参照フィールドによって識別されるクラスのセットがあります。
abstract sealed class Ref(value: String)
case class ARef(value: String) extends Ref(value)
case class BRef(value: String) extends Ref(value)
case class CRef(value: String) extends Ref(value)
trait Referenced {
type refType <: Ref
val ref: refType
}
trait A extends Referenced { type refType = ARef }
trait B extends Referenced { type refType = BRef }
trait C extends Referenced { type refType = CRef }
別のクラス (おそらく State モナドの状態型になる) は、これらの型のリストを含み、参照を指定してオブジェクトを取得する関数を提供します。この戻り値を適切に型付けしたい、つまり与えられた
val aRef = ARef("my A ref")
私は次のような電話をかけることができるようにしたい:
val myA: Option[A] = context.get[A](aRef)
Option[Referenced] だけでなく、Option[A] を必ず返してください。これまでのところ、これを達成するための最善の試みは次のようになります。
trait Context {
// ... other stuff ...
protected val aList: List[A]
protected val bList: List[B]
protected val cList: List[C]
def get[R <: Referenced](ref: R#refType): Option[R] = {
val result = ref match {
case aRef: ARef => aList.find(_.ref == aRef)
case bRef: BRef => bList.find(_.ref == bRef)
case cRef: CRef => cList.find(_.ref == cRef)
case _ => throw new RuntimeException("Unknown Ref type for retrieval: "+ref)
}
result.asInstanceOf[Option[R]]
}
}
これは正しく動作しているように見えますが、その中に「asInstanceOf」呼び出しが含まれています。これがどのように改善されるかについてのアイデアを見たいと思います(そして、明らかに簡単な解決策を見逃していないことを確認してください)。
他の理由で、これまでのところ、パラメーターの型 ( trait A extends Referenced[ARef]
style ) ではなく抽象型付けを使用することを選択しましたが、理由が十分に説得力がある場合はこれを変更できます。