2016-08-23 53 views
0

我有以下的scala代碼。將子類作爲參數傳遞給具有超類作爲參數的函數的參數

trait Super 
case class Sub(value:String) extends Super 
case class YetAnotherSub(value:String) extends Super 
case class OnlyErrorType(value:String) extends Super 

def function1[I <: Super, R](mapper : (I) => R, input: Super) (default: R): R = input match { 
    case error: OnlyErrorType => 
    default 

    case success: I => mapper(success) // Ideally success => mapper(success) 

    case _ => default // I don't want this line at all, as I'm not expecting any other type 
} 

def function2(input:String):Super = if(input.size >= 3) Sub("Greater") else OnlyErrorType("Lesser") 

def function3(input:String):String = { 
    val result = function2(input) 
    function1({sub:Sub => sub.value.toUpperCase}, result) ("Empty Result") 
} 

function3("Input") 

有各種功能類似於function2它接受一些參數和返回的Super任何亞型。我想有一個通用的映射器,像function1,類型爲Super映射到一些其他類型的,但在OnlyErrorType

換句話說情況下返回默認值,我想有一些默認處理爲OnlyErrorType,但讓調用函數(在此例中爲function3)指定SuccessType的映射(除OnlyErrorType之外的Super的任何子類型)。

我該如何做到這一點?

上面的代碼編譯,但我討厭看到警告,

warning: abstract type pattern I is unchecked since it is eliminated by erasure 

我覺得必須有一個更好的方式來做到這一點。

回答

1

這很好,你不喜歡警告;在這種情況下,它基本上意味着測試不起作用。

最簡單的方法就是讓SuccessType明確:

sealed trait Super 
trait SuccessType extends Super 
case class Sub(value:String) extends SuccessType 
case class YetAnotherSub(value:String) extends SuccessType 
case class OnlyErrorType(value:String) extends Super 

def function1[R](mapper: SuccessType => R, input: Super) (default: R): R = input match { 
    case _: OnlyErrorType => default 
    case success: SuccessType => mapper(success) 
} 

注意,因爲Super是密封的,它不能擴展直接其他地方,但它的亞型可以是一個,這樣你就可以添加新的SuccessType s。如果不需要,也可以使用SuccessTypesealed。 當然,在這種情況下,如果function1({case sub:Sub => sub.value.toUpperCase}, result) ("Empty Result")通過YetAnotherSub將失敗。如果這不是你想要的,那麼你需要區分「Super這是Sub如果成功」和「Super這是YetAnotherSub如果成功」靜態。您可以使用

sealed trait Super[I <: Super[I]] 
case class Sub(value:String) extends Super[Sub] 
case class YetAnotherSub(value:String) extends Super[YetAnotherSub] 
case class OnlyErrorType[I <: Super[I]](value:String) extends Super[I] 

def function1[I <: Super[I], R](mapper : (I) => R, input: Super[I]) (default: R): R = input match { 
    case error: OnlyErrorType[_] => 
    default 

    case success => mapper(success.asInstanceOf[I]) 
} 

def function2(input:String):Super[Sub] = if(input.size >= 3) Sub("Greater") else OnlyErrorType("Lesser") 

def function3(input:String):String = { 
    val result = function2(input) 
    function1({sub:Sub => sub.value.toUpperCase}, result) ("Empty Result") 
} 

function3("Input") 

但我寧願不要:在function1投實際上是安全的,但它是不平凡左右(和定義的Super不當,可能會打破它新的亞型)。

+0

我會喜歡你的第一個建議,如果它的工作。它不會編譯。 – nobody

+0

修正了這個建議。 –

相關問題