tags:

views:

578

answers:

4
scala> import java.util.Properties
import java.util.Properties

scala> trait Foo extends Properties
defined trait Foo

scala> classOf[Foo]
res0: java.lang.Class[Foo] = interface Foo

scala> class FooP extends Foo
defined class FooP

scala> classOf[FooP]
res1: java.lang.Class[FooP] = class FooP

scala> classOf[Properties with Foo]
<console>:7: error: class type required but java.util.Properties with Foo found
       classOf[Properties with Foo]
               ^

scala> new Properties with Foo
res2: java.util.Properties with Foo = {}

scala> res2.getClass
res3: java.lang.Class[_] = class $anon$1

Is there a way of getting class of 'Properties with Foo' without creating an instance or new class?

+1  A: 

No it is not possible because "X with Y" is an anonymous definition in your example. This is not the case for "class X extends Z with Y" of course.

Joa Ebert
+5  A: 

classOf[X] only works if X corresponds to a physical class. T with U is a compound type, and doesn't correspond to a class.

You can use Manifests to determine the erasure of a type. The type erasure of T with U is T.

scala> trait T
defined trait T

scala> trait U
defined trait U

scala> manifest[T with U]
res10: Manifest[T with U] = T with U

scala> manifest[T with U].erasure
res11: java.lang.Class[_] = interface T

Here you can see that List[Int] and List[_] have the same erasure:

scala> classOf[List[_]]
res13: java.lang.Class[List[_]] = class scala.collection.immutable.List

scala> classOf[List[Int]]
res14: java.lang.Class[List[Int]] = class scala.collection.immutable.List

scala> classOf[List[Int]] == classOf[List[_]]
res15: Boolean = true
retronym
but (new T with U).getClass does return a class. What is it then?
IttayD
`new T with U` declares and instantiates an anonymous class that implements the interfaces `T` and `U`.
retronym
A: 

You can't get a class literal but you can test if an object meets that type in two different ways:

trait X
trait Y

val xy: AnyRef = new X with Y
val zz: AnyRef = new Object with X

xy.isInstanceOf[X with Y] // true
zz.isInstanceOf[X with Y] // false

xy match { case a: X with Y => true; case _ => false} // true
zz match { case a: X with Y => false; case _ => false} // false

It's a lot like this generic declaration in java

public <T extends Comparable<T> & Serializable> T id(T t) { return t; }

That method gets erased to

public Comparable id(Comparable t) { return t; }

However in Java you cannot say xy instanceof (X&Y) but it's really the same as xy instanceof X && xy instanceof Y

Geoff Reedy
A: 

I'm not sure exactly what you're trying to do with the composite class, but what you can do is get the list of interfaces implemented and the superclass of a given anonymous class which might suffice. For example:

trait X
trait Y
class Foo
val bar = new Foo with X with Y
val barClass = bar.getClass // class $anon$1
barClass.getInterfaces // Array(interface X, interface Y)
barClass.getSuperclass // class Foo
coopf
What I wanted is to get the composition class without creating an instance or new class
IttayD