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

mas*_*boo 3 types scala

我已经检查它是否是下面的函数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")
} 
Run Code Online (Sandbox Code Playgroud)

要么

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

以下是检查: -

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
}
Run Code Online (Sandbox Code Playgroud)

muc*_*aho 6

正如在其他答案中所提到的,类型擦除使得匹配表达式检查List而不是List[Int],因此结果不像人们预期的那样.

但是,您可以使用TypeTags来规避多态类型的类型擦除.需要注意的是TypeTagS ^ 可能使用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
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它

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))
Run Code Online (Sandbox Code Playgroud)


Dae*_*yth 5

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

在运行时,类型TList,而不是List[String]List[Int]

事实上,你试图做到这一点就会产生很大的代码味 - 你怎么不知道你拥有什么?