2016-02-29 140 views
1

消除返回类型考虑下面的Scala代码片段:通过擦除斯卡拉

def func(param: Any): Int = param match { 
    case f: (String => Int) => f("apple") 
    case i: Int => i 
} 

println(func((s: String) => s.length)) 

正常工作,但是,在编译时,我得到以下警告:

<console>:11: warning: non-variable type argument String in type pattern String => Int is unchecked since it is eliminated by erasure 
     case f: (String => Int) => f("apple") 

我怎样才能摆脱此警告讯息?

感谢您的帮助提前!

回答

3

收到消息的原因是因为Java的通用type erasure。在这种情况下,您的Function[String, Int]类型的功能将与任何Function[A, B]匹配。

为了摆脱这个警告,你应该使用scala typetags这将允许你区分不同的功能类型。

的代码片段是以下,

import scala.reflect.runtime.universe._ 

object Answer { 
def function[A](param: A)(implicit tt: TypeTag[A]): String = param match { 
    case f: (String => Int) @unchecked if typeOf[String => Int] =:= typeOf[A] => f("apple").toString 
    case f: (Int => String) @unchecked if typeOf[Int => String] =:= typeOf[A] => f(32 + 1) 
    case s: String => s"hello $s" 
    } 

    def main (args: Array[String]) { 
    println(function((s: String) => s.length)) 
    println(function((i: Int) => i.toString)) 
    println(function("world")) 
    } 
} 

的关键部分是有一个implicitTypeTag[A]它是在编译时,其包括该功能typeOf需要检查类型的A针对别的元数据添加。

+0

感谢您的解释和链接!我试图解决警告但失败。现在我对'TypeTag'的含义有了一个理论上的认识,而且我知道'case f:((_)=>(_))=>'不会抱怨。但是,在后一种情况下,'f(...)'会导致编译器错误。请您这么友好地给我一些进一步的提示如何继续?谢谢! –

+0

用代码片段更新。 – yw3410

+0

感谢您的解释性代码!它确实更精确,因为我们现在可以区分String => Int和Int => String。我已经尝试过了,但不幸的是现在有两次同样的警告。 我尝试了以下方法:'type oneParamFuncType = _ => _',并且在两种情况下都使用'case f:oneParamFuncType ...',但是,这会导致函数调用时发生编译器错误。如果没有函数调用,编译器会很高兴。你有没有想法如何将通用'oneParamFuncType'转换为特定的? –