我正在尝试返回参数化类型Output[T <: Input]
的子类但由于某种原因我似乎无法正确使用语法:
sealed trait Input
case class A(id: Int) extends Input
case class B(id: String) extends Input
sealed trait Output[+T <: Input]
case class OutA(some: String) extends Output[A]
case class OutB(thing: Int) extends Output[B]
def doStuff[T <: Input, RT <: Output[T]](input: T): RT =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: RT
// case A(i) => OutA(i.toString)
//
// error: type mismatch;
// found : OutB
// required: RT
// case B(s) => OutB(s.toInt)
def doStuff[T <: Input](input: T): Output[T] =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: Output[T]
// case A(i) => OutA(i.toString)
// error: type mismatch;
// found : OutB
// required: Output[T]
// case B(s) => OutB(s.toInt)
def doStuff[T <: Input, RT <: Output[_]](input: T): RT =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: RT
// case A(i) => OutA(i.toString)
// error: type mismatch;
// found : OutB
// required: RT
// case B(s) => OutB(s.toInt)
在我的实际代码中,Input
和Output
子类被包装在我无法修改的容器中,输入也来自另一个我无法控制的系统。但是,这似乎是我能想到的最小的例子,我得到了相同的编译时类型错误。
如何解决我的问题?
答案 0 :(得分:0)
你可以这样做(这是Scala中type class的一个例子,搜索这个术语会给你很多帖子解释模式):
case class StuffDoer[T](doStuff: T => Output[T])
object StuffDoer {
implicit val ADoer: StuffDoer[A] = StuffDoer(x => OutA(x.id.toString))
implicit val BDoer: StuffDoer[B] = StuffDoer(x => OutB(x.id.toInt))
implicit val InputDoer: StuffDoer[Input] = StuffDoer {
case a: A => ADoer.doStuff(a)
case b: B => BDoer.doStuff(b)
}
}
def doStuff[T](input: T)(implicit doer: StuffDoer[T]) = doer.doStuff(input)
(实际上,这个问题的某些变体会不时被问到,但是写答案比搜索以前的问题要快。)