Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between scala's ClassTag and TypeTag

According to scala doc,TypeTag contains more information than ClassTag. It seems to me that TypeTag can do more things than ClassTag, like bring the type parameter information of compile time to runtime, etc.

However, the following example shows that ClassTag can do the job, while the TypeTag not. I want to understand why.

import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag
// def func[T](o: Any): Unit = {
// def func[T : TypeTag](o: Any): Unit = {
def func[T : ClassTag](o: Any): Unit = {
  o match {
    case x: T => println(Some(x))
    case _ => println(None)
  }spark
}
func[Map[Int, Int]](List(1, 2, 3))

Only ClassTag will lead the pattern matching to None (which is the expected behavior), the first two commented lines will come up with Some branch.

It seems that ClassTag can reflect on object's type on runtime, while TypeTag can't. But isn't TypeTag a superset of ClassTag? I would like to know the explanation as detailed as possible. Thank you.

like image 626
Hao Ren Avatar asked Oct 23 '16 11:10

Hao Ren


People also ask

What is a TypeTag?

A TypeTag is completely compiler-generated, that means that the compiler creates and fills in a TypeTag when one calls a method expecting such a TypeTag . There exist three different forms of tags: scala. reflect. ClassTag.

What is Scala ClassTag?

A ClassTag[T] stores the erased class of a given type T , accessible via the runtimeClass field. This is particularly useful for instantiating Array s whose element types are unknown at compile time.

What is manifest in Scala?

A Manifest[T] is an opaque descriptor for type T. Its supported use is to give access to the erasure of the type as a Class instance, as is necessary for the creation of native Arrays if the class is not known at compile time.

What is Scala reflect?

Scala reflection enables a form of metaprogramming which makes it possible for programs to modify themselves at compile time. This compile-time reflection is realized in the form of macros, which provide the ability to execute methods that manipulate abstract syntax trees at compile-time.


1 Answers

this page will help you!
take a look :)

https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20

add more detail, since only link answer is not appropriate...

ClassTag : runtime information about value, but not good with generic style
TypeTag : runtime information about type

e.g.

object Test extends App {

  import scala.reflect.ClassTag
  def func[T : ClassTag](o: Any): Unit = {
    o match {
      case x: T => println(x)
      case _ => println(None)
    }
  }
  func[List[String]](List(1, 2, 3)) // List(1, 2, 3), not None!!! with List[String] type parameter... ClassTag only recognize List scale, not List[T]

  import scala.reflect.runtime.universe._
  def func2[T](o: T)(implicit tag: TypeTag[T]): Unit = {
    tag.tpe match {
      case TypeRef(utype, usymbol, args) => println(args.toString)
      case _ => println(None)
    }
  }
  func2(List(1, 2, 3)) // List(Int)
}
like image 180
Curycu Avatar answered Sep 24 '22 01:09

Curycu