将Subclass作为参数传递给函数,该函数以Super类作为参数获取任何函数

时间:2016-08-23 13:22:14

标签: scala types pattern-matching

我有以下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

我认为必须有更好的方法来做到这一点。

1 个答案:

答案 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定义新的子类型不正确可能会破坏它。)