February 26, 2009

class what?

I'm a little annoyed that this doesn't work:

scala> class Foo
defined class Foo

scala> object Thing extends Foo
defined module Thing

scala> val set = scala.collection.immutable.Set[Class[_ <: Foo]](Thing.getClass)
<console>:6: error: type mismatch;
found : java.lang.Class[?0] where type ?0
required: Class[_$1] forSome { type _$1 <: Foo }
val set = scala.collection.immutable.Set[Class[_ <: Foo]](Thing.getClass)
^

I'm sure it's probably a java compatibility thing, but shouldn't the class of an object of type T return a class of type Class[T]?

6 comments:

James Iry said...

class NiceObject[T <: AnyRef](x : T) {
def niceClass : Class[_ <: T] = x.getClass.asInstanceOf[Class[T]]
}

implicit def toNiceObject[T <: AnyRef](x : T) = new NiceObject(x)

scala> "Hello world".niceClass
res11: java.lang.Class[_ <: java.lang.String] = class java.lang.String

Unknown said...

However,

Thing.isInstanceOf[Foo]
res10: Boolean = true

The only problem with your code is the syntax. Thing.getClass should be replaced with classOf[Thing], only that doesn't work because Thing is an object. I'm sure there is a way to do what you want, but I don't know how to use classOf with objects.

James Iry said...

scala> import scala.reflect.Manifest
import scala.reflect.Manifest

scala> def classOf[T](implicit mfst : Manifest[T]) = mfst.erasure.asInstanceOf[Class[T]]
classOf: [T](implicit scala.reflect.Manifest[T])Class[T]

scala> classOf[String]
res0: Class[String] = class java.lang.String

Unknown said...

See #490.

Robey said...

It looks like even THIS solves it:

def classOfObj[T <: AnyRef](x: T) = x.getClass.asInstanceOf[Class[T]]

which confirms this is a scala bug.

David R. MacIver said...

Note that it is not correct that (x : T).getClass should return a Class[T]. It should return a Class[_ <: T], as JamesIry posted. Class is invariant, and you might have a subclass.