【问题标题】:Can we match Any to a generic type? [Scala 2.8]我们可以将 Any 匹配到泛型类型吗? [斯卡拉 2.8]
【发布时间】:2011-06-19 01:44:59
【问题描述】:

如果之前已经回答过,请指点我更正的链接。

我有这个代码:

def getResult(a:Any):Any = a

def getAnswer[T](i:Int) = {
  val result = getResult(i)
  result match {
    case t:T => Some(t)
    case _ => None
  }
}

这给了我一个unchecked warning,并且所有内容都与T 匹配。例如,当我执行getAnswer[Int](2) 时,我得到Some(2)(如预期的那样)。但是,如果我执行getAnswer[String](2),我也会得到Some(2),这是意料之外的(我需要None)。

有没有办法解决类型擦除并以某种方式让getAnswer 正常工作(即,当且仅当结果是T 类型时才返回Some(result))?

提前致谢。

【问题讨论】:

    标签: scala scala-2.8


    【解决方案1】:
    def getAnswer[T](i:Any)(implicit m:Manifest[T]) = i match {
        case t:Int if m.erasure == classOf[Int] => Some(t)
        case t:Double if m.erasure == classOf[Double] => Some(t)
        //... other Primitives  
        case t if m.erasure.isInstance(t) => Some(t) //this matches AnyRefs
        case _ => None
    }
    

    正如 Alexey 所写,您在使用原语时遇到了一些麻烦。在这种情况下,Scala 源代码中使用的技术总是为每个原始类型单独匹配,所以我想没有办法。

    【讨论】:

    • 感谢您对如何处理原语的回答。 Alexey 的回答也不错。
    • 我选择你的答案是正确的,因为它可以处理原始类型。再次感谢您的代码。
    【解决方案2】:

    这有一些限制(T 必须是类而不是原始类型;如果 T 是泛型,则忽略参数)。

    def getAnswer[T](i:AnyRef)(implicit m:ClassManifest[T]) = {
      val result = getResult(i)
      if (result.getClass == m.erasure) Some(result.asInstanceOf[T]) else None
    }
    
    > getAnswer[java.lang.Integer](2.asInstanceOf[AnyRef])
    res4: Option[java.lang.Integer] = Some(2)
    
    getAnswer[String](2.asInstanceOf[AnyRef])
    res1: Option[String] = None
    

    【讨论】:

    • 我们需要修改getResult 也返回AnyRef。就我而言,T 始终是一个类或对象,而不是原始类型,所以这可能对我有用。我会检查并恢复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多