对不起,但我想不出更好的标题(建议欢迎)。
基本上我有一个类层次结构,子类有一个类型成员,表示“它们应该映射到哪种类型”。然后我想要一个为这些类型实现某种异构映射的类。请参阅以下代码作为示例。
我的问题是我是否(以及如何)在不诉诸演员的情况下将其付诸实践。如果它不起作用,请解释原因。
trait A {
type Result
}
case class AInt(id: String) extends A {
type Result = Int
}
case class AString(id: String) extends A {
type Result = String
}
class AStore {
val mapInt = new collection.mutable.HashMap[String,Int]()
val mapString = new collection.mutable.HashMap[String,String]()
def put[T <: A](t: T, result: T#Result) {
t match {
case AInt(id) => mapInt(id) = result
case AString(id) => mapString(id) = result
}
}
def get[T <: A](t: T): T#Result = t match {
case AInt(id) => mapInt(id)
case AString(id) => mapString(id)
}
}
尝试编译它会产生以下错误消息:
19: error: type mismatch;
found : T#Result
required: Int
case AInt(id) => mapInt(id) = result
^
20: error: type mismatch;
found : T#Result
required: String
case AString(id) => mapString(id) = result
^
25: error: type mismatch;
found : Int
required: T#Result
case AInt(id) => mapInt(id)
^
26: error: type mismatch;
found : String
required: T#Result
case AString(id) => mapString(id)
^
four errors found
答案 0 :(得分:3)
这不是一个简单的原因:在
def put[T <: A](t: T, result: T#Result) {
t match {
case AInt(id) => mapInt(id) = result
case AString(id) => mapString(id) = result
}
}
T
的范围是整个方法定义,因此您不能在不同的分支中使用不同的T#Result
。
您可以查看GADTs。
这是链接帖子给出的编码的例子:
trait A[Result] {
def id: String
}
case class AInt(id: String) extends A[Int]
case class AString(id: String) extends A[String]
class AStore {
val mapInt = new collection.mutable.HashMap[String,Int]()
val mapString = new collection.mutable.HashMap[String,String]()
def put[Result](t: A[Result], result: Result) {
t match {
case AInt(id) => mapInt(id) = result
case AString(id) => mapString(id) = result
}
}
def get[Result](t: A[Result]): Result = t match {
case AInt(id) => mapInt(id)
case AString(id) => mapString(id)
}
}