Why does Scala "handle" ClassTags automatically?

Class tags seem very easy to use, however, is it not always possible to reliably automatically insert a ClassTag template in at least some scripts, if not all? Consider this example:

 def foo[T: ClassTag] = { val cls = classTag[T].runtimeClass.asInstanceOf[Class[T]] val myList: Seq[T] = parseList(rawJson, cls) // let assume parseList a library method that needs to work with a Class instance (eg RestFB fetchConnnection) ... } 

why not Scala write instead:

 def foo[T] = { val cls = classOf[T] val myList: Seq[T] = parseList(rawJson, cls) // let assume parseList a library method that needs to work with a Class instance (eg RestFB fetchConnnection) ... } 

... and automatically convert the last to the first?

Is there a technical reason for this, for example. The desirability of class tags cannot always be reliably determined by the compiler / reflection library? Or is it a purely conscious design choice to keep it explicit? For example, to encourage a programmer to avoid having to use class labels in the first place for cleaner design and better performance, even if he knew that in many cases this is not possible?

PS I do not ask why Scala does not offer (and does not offer) to add ClassTag magic for each method definition using a type parameter; I just ask why this cannot be done automatically when it is necessary / inevitable.

+6
source share
1 answer

This syntax is:

 def foo[T: ClassTag] = ... 

actually a shorthand for this:

 def foo[T](implicit ev: ClassTag[T]) = ... 

This means that if a ClassTag[T] was provided for each type parameter of the type, then each function would have an additional hidden parameter or even several.

This, of course, is completely undesirable. One of the most notable drawbacks of this approach is the almost broken Java compatibility when using generics:

 SomeClass someClass = new SomeClass(); someClass.foo<Integer>(ClassTag.apply(Integer.class)); 

Introduce more complex general methods and parameters. And this is only for the possibility of comparing with a common type, which is almost never needed.

Calling standard Java methods will also be mixed. Which method should be called here:

 val jc = new JavaClass jc.foo[Int]() 

if JavaClass is defined as follows:

 public class JavaClass { public <T> void foo() { ... } public <T> void foo(ClassTag<T> ct) { ... } } 

?

Of course, if Java supported reified generics, everything would be different ...

+4
source

All Articles