我有以下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的映射(Super
的任何子类型除了OnlyErrorType
)。
我如何实现这一目标?
上面的代码编译,但我讨厌看到警告,
warning: abstract type pattern I is unchecked since it is eliminated by erasure
我认为必须有更好的方法来做到这一点。
答案 0 :(得分: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
秒。如果不合适,请同时SuccessType
sealed
。
当然,在这种情况下function1({case sub:Sub => sub.value.toUpperCase}, result) ("Empty Result")
如果通过YetAnotherSub
则会失败。如果那不是您想要的,那么您需要区分&#34; Super
Sub
如果成功&#34;和#34; Super
YetAnotherSub
如果成功&#34;静态。你可以使用
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
定义新的子类型不正确可能会破坏它。)