Scala在转换为泛型时遇到麻烦

时间:2014-10-29 08:31:35

标签: scala generics casting

我尝试根据输入类型编写一些执行不同操作的函数。 例如,我这样做:

def Foo[T](inList: List[String]): ArrayBuffer[T] = {
  val out: ArrayBuffer[T] = new ArrayBuffer[T]()
  inList.map ( x => {
    val str = x.substring(1)
    out += str.asInstanceOf[T]
  })
  out
}

但是如果我用Foo[Long](new List("123","2342"))调用此函数,我会得ArrayBufferString,而不是Long。对不起我的noob问题,我想了解scala和泛型。

2 个答案:

答案 0 :(得分:4)

  1. Scala在JVM上运行,它对泛型一无所知,并且在运行时没有具体的泛型类型。
  2. 因此,运行时等效的代码看起来像

      def Foo(inList: List[String]): (ArrayBuffer[Object]) = {
        val out: ArrayBuffer[Object] = new ArrayBuffer[Object]()
        inList.map ( x => {
          val str=x.substring(1)
          out += str.asInstanceOf[Object]
        })
        (out)
      }
    
    1. asInstanceOf不会将字符串转换为long,而是会抛出不兼容类型的异常。相反,您应该为函数提供从字符串到另一种类型的转换。
    2. 总结一下,您的代码应如下所示:

        import scala.collection.mutable.ArrayBuffer
      
        // here we define how convert string to longs
        implicit def stringToLong(s: String) = s.toLong
      
        // now this function requires to have converter from string to T in context
        def Foo[T](inList: List[String])(implicit f: (String) => T): (ArrayBuffer[T]) = {
          val out: ArrayBuffer[T] = new ArrayBuffer[T]()
          inList.map { x => 
            val str = x.substring(1)
            out += f(str) // here we apply converter
          }
          out
        }
      
        // when function is called, appropriate implicit converter from context will be used
        Foo[Long](List("51", "42"))
      

答案 1 :(得分:1)

String转换为Long并不会使它成为Long,这是一个错误,因此您应该收到运行时错误,指出您无法将String转换为Long。由于T没有对它的内容进行任何限制,因此您不能期望调用任何不在所有对象上的方法(例如toString)。您可以自己提供该功能(这几乎是地图的确切签名,因此您可以使用它):

def convert[T](in: List[String])(convert: String => T): List[T] =
  in.map(convert)

或者确保对象属于您知道方法的类型(使用类型绑定):

trait CanConvertTo[T] {
  def convert: T
}

case class Example(value: String) extends CanConvertTo[Long] {
  def convert = value.toLong
}

def convert[T](in: List[CanConvertTo[T]]): List[T] = in.map(_.convert)