2016-08-23 129 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

修正了这个建议。 –

相关问题