Closed scabug closed 13 years ago
Imported From: https://issues.scala-lang.org/browse/SI-490?orig=1 Reporter: @blair
@SethTisue said: I find I am hitting this issue in my own code. +1 on an eventual fix; Scala has taken a step backward from Java in this respect.
Lauri Alanko (lealanko) said:
There is a similar issue for classOf[]
. Whereas the type of getClass()
is currently too weak, the type of classOf[]
is too strong:
scala> classOf[List[int]]
res4: java.lang.Class[List[int]] = class scala.List
scala> classOf[List[String]]
res5: java.lang.Class[List[String]] = class scala.List
That is, the type system claims that the class object is a representation of a type application, even though there is no real run-time information about the type argument.
I think it would be desirable for the property to hold that if (a : Class[A]) eq (b : Class[B])
, then A <: B <: A
. This is not currently true.
So I suggest that classOf
gets the same treatment as is suggested for getClass
: let the type of classOf[A]
be Class[B]
where B
is the "existential erasure" of A (or whatever is the upper bound of all types that share the erasure of A), i.e.:
classOf[List[A]] : Class[List[T] forSome { type T }]
@SethTisue said: see also #4696
Commit Message Bot (anonymous) said: (extempore in r25137) A total rewrite of "runtimeClass", discarding the user-space approach in favor of simply fixing getClass.
def f1 = 5.getClass // Class[Int] def f2 = (5: AnyVal).getClass // Class[ <: AnyVal] def f3 = (5: java.lang.Integer).getClass // Class[ <: java.lang.Integer]
class A class B extends A
def f1 = (new B: Any).getClass().newInstance() // Any def f2 = (new B: AnyRef).getClass().newInstance() // AnyRef def f3 = (new B: A).getClass().newInstance() // A def f4 = (new B: B).getClass().newInstance() // B
But that's not all!
def f0[T >: B] = (new B: T).getClass().newInstance()
def f5 = f0[Any] // Any def f6 = f0[AnyRef] // AnyRef def f7 = f0[A] // A def f8 = f0[B] // B
Closes #490, #896, #4696. Review by moors. (Note: I think this is pretty good, but picky review requested.)
It would be useful if Scala were to treat the return from getClass() as a java.lang.Class[T] forSome { val T : C } where C is something like the erasure of the static type of the expression on which getClass is called. This would match Java 6:
http://java.sun.com/javase/6/docs/api/java/lang/Object.html#getClass()
It would let me do something like the following where I want to introspect on a class but shouldn't need a class instance. I also want to limit the types of classes I want to introspect on, so I use Class[_ <: Foo]. But this prevents me from passing in a Foo class by using Foo.getClass() without a cast.
There was a request for this and Martin responded:
http://scala-programming-language.1934581.n4.nabble.com/Java-generics-vs-Scala-types-td1937960.html