2017-07-04 120 views
0

我試圖返回一個參數化類型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) 

在我實際的代碼InputOutput子類被封裝在容器中,我無法修改,輸入也來自另一個我無法控制的系統。然而,這似乎是我能想到的最小的例子,我得到相同的編譯時類型錯誤。

我該如何解決我的問題?

回答

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) 

(說真的,有些變化這個問題會不時問到,但是寫出答案比搜索以前的問題要快。)