我正在尝试为以下情况编写“更好”(更惯用?)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 monad 的状态类型)将包含这些类型的列表,并提供一个函数来检索对象,给定它的引用。我希望这个返回值被适当地输入,即给定
val aRef = ARef("my A ref")
我希望能够拨打如下电话:
val myA: Option[A] = context.get[A](aRef)
并确保返回一个 Option[A],而不仅仅是一个 Option[Referenced]。到目前为止,我实现这一目标的最佳尝试如下所示:
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]
样式),但如果理由足够令人信服,可以改变这一点。