Scala是如何发生的以及为什么

时间:2015-02-21 12:24:14

标签: scala types

我有以下功能来检查它是List[Int]还是List[String]。但如果我检查如下,总是如此。为什么以及如何定义检查List[Int]List[String]类型的函数。

if(checkIntCollection(List("q","aa","aa"))){
    Logger.info("it is true")
} else {
    Logger.info("it is false")
} 

OR

if(checkIntCollection(List(1,2,3))){
    Logger.info("it is true")
} else {
    Logger.info("it is false")
}

以下是检查: -

def checkIntCollection[T](v: T) : Boolean = v match {
    case _: List[Int] =>
      Logger.info("It is List[Int] found")
      true
    case _ =>
      Logger.info("It is unknown")
      false
}

def checkStringCollection[T](v: T) : Boolean = v match {
    case _: List[String] =>
      Logger.info("It is List[String] found")
      true
    case _  =>
      Logger.info("It is unknown")
      false
}

2 个答案:

答案 0 :(得分:6)

正如其他答案中所述,类型擦除会使您的匹配表达式检查List而不是List[Int],因此结果并非人们所期望的那样。

但是,您可以使用TypeTag来规避多态类型的类型擦除。请注意,TypeTag s 可能使用Reflection,这可能会对性能产生负面影响。

import scala.reflect.ClassTag
import scala.reflect.runtime.universe._

object RichClass {
  def unapply[T](a: RichClass[T]): Option[T] = Option(a.value)
}
implicit class RichClass[T](val value: T)(implicit val classTag: ClassTag[T], val typeTag: TypeTag[T]) {}

def isType[T : ClassTag : TypeTag](richClass: RichClass[_]): Boolean = {
  richClass match {
    case RichClass(elem: T) if richClass.typeTag.tpe =:= typeOf[T] => true
    case _ => false
  }
}

然后你可以像这样使用它

val stringList = List("A", "B")
val intList = List(1, 2, 3)

assert(isType[List[String]](stringList))
assert(!isType[List[String]](intList))
assert(isType[List[Int]](intList))
assert(!isType[List[Int]](stringList))

答案 1 :(得分:5)

由于类型擦除,这种情况正在发生。如果使用警告编译,您会注意到它表示您的类型测试没用,因为包含的类型在运行时不可见。

在运行时,T的类型为List,而不是List[String]List[Int]

事实上,你正试图在所有方面做到一个大代码的味道 - 你怎么不知道你有什么?