Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getClass() return java.lang.Class[T] forSome { val T : C } #490

Closed
scabug opened this issue Feb 16, 2008 · 5 comments
Closed

getClass() return java.lang.Class[T] forSome { val T : C } #490

scabug opened this issue Feb 16, 2008 · 5 comments
Assignees

Comments

@scabug
Copy link

scabug commented Feb 16, 2008

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.

trait IdlBase

class IdlConcrete

object Test extends Application {
  // In general, this method should not need an instance to reflect on it, so
  // take a Class[]
  def reflect(clazz : Class[_ <: IdlBase]) = {
    // Get a list of all its methods and build a hash keyed by method name
    // for statistics recording.
  }

  // But I also really have an IdlConcrete generated by Spring here...
  val idl = new IdlConcrete
  reflect(idl.getClass)
}
test.scala:14: error: type mismatch;
 found   : java.lang.Class[?0] where type ?0
 required: Class[_$$1] forSome { type _$$1 <: IdlBase }
  reflect(idl.getClass)
              ^
one error found

There was a request for this and Martin responded:

http://scala-programming-language.1934581.n4.nabble.com/Java-generics-vs-Scala-types-td1937960.html

@scabug
Copy link
Author

scabug commented Feb 16, 2008

Imported From: https://issues.scala-lang.org/browse/SI-490?orig=1
Reporter: @blair

@scabug
Copy link
Author

scabug commented Apr 3, 2008

@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.

@scabug
Copy link
Author

scabug commented Apr 24, 2008

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 }]

@scabug
Copy link
Author

scabug commented Jun 21, 2011

@SethTisue said:
see also #4696

@scabug
Copy link
Author

scabug commented Jun 22, 2011

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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants