为什么Scala方法isInstanceOf[T]不起作用

7fyelxc5  于 2023-05-21  发布在  Scala
关注(0)|答案(2)|浏览(190)

为什么isInstanceOf[T]方法不能正常工作?

在下面,我定义了一个hello类和伴随对象。在Hello对象中,我在代码行“hel.typetest[Int]”中测试了this.isInstanceOf[T],当类型TInt时,为什么这是true

object hello {
  def main(args: Array[String]): Unit = {
    Console.println("main")
    val hel = new hello
    hel.typetest[Int]
  }
}

class hello {
  def typetest[T: ClassTag]: Unit = {
    Console.println(this.isInstanceOf[T])
    Console.println(this.getClass)
  }
}

产出:

main
true
class hello
6gpjuf90

6gpjuf901#

因为type erasure(连同拳击)。T擦除为Object,因此this.isInstanceOf[T]在字节码中变为this.isInstanceOf[Object],这始终是正确的。
碰巧,ClassTag旨在避免这种情况,但您需要实际使用它,而不是调用isInstanceOf

def typetest[T](implicit tag: ClassTag[T]): Unit = {
  Console.println(tag.runtimeClass.isInstance(this))
}

当存在ClassTag时,还有用于模式匹配T的特殊情况support

def typetest[T: ClassTag]: Unit = {
  Console.println(this match {
    case _: T => true
    case _ => false
  })
}

ClassTag也存在时,有人建议让is/asInstanceOf[T]正常工作,但编译器中内置了一些假设,这些假设阻止了这一点,并且太难更改(如果我没有记错原因的话)。

svmlkihl

svmlkihl2#

在搜索了许多帖子并与类型擦除警告作斗争后,我在模式匹配中发现了这个堆栈溢出答案隐式ClassTag
基于那篇文章,我创建了下面的隐式类型匹配器来检查对象是否是泛型类型T的示例。希望这能对某些人有所帮助。

import scala.reflect.ClassTag

object ObjectExtensions {
  implicit class IsType(obj: Object) {
    def isType[T](implicit tag: ClassTag[T]): Boolean = obj match {
      case tag(_: T) => true
      case _ => false
    }
  }
}

**编辑:经过进一步研究,您需要使用classTag[T].runtimeClass.isInstance(objectToCheck),而不是使用isInstanceOf[T],正如Alexey Romanov的回答所指出的那样。

import scala.reflect.ClassTag

object ObjectExtensions {
  implicit class IsType(obj: Object) {
    def isType[T : ClassTag](): Boolean = {
      classTag[T].runtimeClass.isInstance(obj)
    }
  }
}

相关问题