Issues with manifest / typetags when upgrading to Scala 2.10


I sit in front of the project for about 10,000 LoC. I need to upgrade this project from Scala 2.9 to 2.10. This was well done, but because of the manifest, I got a lot of warnings about deprecation.

After using the stackoverflow search function and many other sites, I don't have many questions. I want to summarize; key points:

  • TypeTags and ClassTags are much better than Manifests and ClassManifest. Especially you can use them as synonyms (TypeTags โ†” Manifests and ClassTags โ†” ClassManifest)

  • TypeTags are more powerful than ClassTags, respectively ClassTags are more limited to TypeTags. My first question: The manifest[T].erasure.getSimpleName method is often used in this project. Now I can not only switch this to typeTag[T].runtimeClass.getSimpleName , because the code will not compile, but with classTag[T].runtimeClass.getSimpleName it will compile. Will this affect semantics? (Note: the erasure method is also deprecated, you should use runtimeClass )

  • Second question: The manifest type check in Scala 2.9 was like: manifest[T] <:< manifest[A] . In Scala 2.10, I would write this typeOf[T] <:< typeOf[A] . But <:< out of date ?!

  • Is it possible to apply TypeTag to ClassTag? That is: If I use manifests only for type checking (No. 3) and extracting a name (No. 2): Can I rename each manifest / class manifest to ClassTag?

+4
source share
1 answer
  • Yes, you basically have the equivalence of TypeTag <-> Manifest and ClassTag <-> ClassManifest . Also, there are some things that were previously handled by Manifests that do not have a direct equivalent, because these operations were moved deeper into the reflection API, for example, the factory methods of the Manifest object.

  • ClassTag now mainly used only to get the runtime (erase) class. The main thing is to create an array for this, but you can use it for other purposes without any problems. So yes, classTag[T].runtimeClass is the new manifest[T].erasure and is fully equivalent to it.

  • This is the place that has changed the most. 2.10 introduced the new reflection API , and you should use it when you want to answer specific questions about types (for example, A <:< B ? "). And the entry point to the reflection API for a type is ... its TypeTag .

    Assuming the type tags for A and T are in scope, the new manifest[T] <:< manifest[A] will really be typeOf[T] <:< typeOf[A] . The <:< method is not used here, see the scaladoc file . However, ClassTag no deprecated <:< in ClassTag because ClassManifest used it and ClassTag new ClassManifest .

    See the General Types of Operations section of the reflection guide and the SO question What is TypeTag and how to use it .

  • I don't think there is a direct path from TypeTag to ClassTag . Think of it this way:

    • if you need subtyping or type equality checking, you cannot use ClassTag , you need TypeTag ;

    • if you also need a name for this type, you can simply get it from TypeTag : typeOf[T].typeSymbol.name.decoded . This will give you the erased name, like the name of the class you used to get ( List for List[Int] , or Map for Map[String, Int] ). This is slightly different than getting the name of the actual Class . If you need a complete unused name ( List[Int] ), typeOf[T].normalize.toString enough.

    • if you also need an instance of Class or the name of a real class that you can transfer and load later with reflection, I think you have no choice but to request a ClassTag too ClassTag strike>

      Edit : I just found this SO question , so yes, you can get a ClassTag from TypeTag . It's just sad that there is no helper method in the reflection library.

      Edit 2 : as required, here's how to convert from TypeTag to ClassTag :

       import reflect.runtime.universe._ import reflect.ClassTag def classTag2[T: TypeTag]: ClassTag[T] = { ClassTag[T]( typeTag[T].mirror.runtimeClass( typeTag[T].tpe ) ) } // example: def doSomething[T : TypeTag] = { val c = classTag2[T] c.runtimeClass.getName } 
+5
source

Source: https://habr.com/ru/post/1493817/


All Articles