tags:

views:

104

answers:

3

And more specific example:

abstract trait A
trait B extends A
trait C extends A

How to check what traits that extend trait A (it can be from 0 to many) were mixed in specified class?

+1  A: 
scala> val x = new A with B with C
x: java.lang.Object with A with B with C = $anon$1@8ea25fa

scala> x.getClass.getInterfaces
res11: Array[java.lang.Class[_]] = Array(interface A, interface B, interface C)
Adam Rabung
I had thought about this obvious method but decided to ask here because traits as I know can compile in sophisticated ways.
Jeriho
Never resort to using reflection when the language features suffice.
Randall Schulz
Agreed. I first used isInstanceOf - which replied to the body of his question. But I switched to getInterfaces when I re-read his actual question title "How to get list of traits...".
Adam Rabung
Ah. The reading comprehension aspect... There will, in the not-too-distant-future, be a Scala-specific reflection interface, but I believe it is currently nascent. (Sorry, but I can no longer undo my down-votes on the reflection-based ansers.)
Randall Schulz
A: 

How about something like this:

def getTraitsExtending(clazz:Class[_], baseTrait:Class[_]): Seq[Class[_]] = {
  clazz.getInterfaces().filter { baseTrait isAssignableFrom _ }
}

This finds all traits that clazz implements that are themselves subtraits of baseTrait. With the following traits:

trait A
trait B extends A
trait C extends A
trait D

Use as follows:

scala> val x1 = new C with B
x1: java.lang.Object with C with B = $anon$1@51d92803

scala> getTraitsExtending(x1.getClass, classOf[A])
res0: Seq[Class[_]] = WrappedArray(interface C, interface B)

scala> val x2 = new C with A            
x2: java.lang.Object with C with A = $anon$1@f8db08

scala> getTraitsExtending(x2.getClass, classOf[A])
res1: Seq[Class[_]] = WrappedArray(interface C, interface A)

scala> val x3 = new C with D             
x3: java.lang.Object with C with D = $anon$1@2bbd83d

scala> getTraitsExtending(x3.getClass, classOf[A])
res3: Seq[Class[_]] = WrappedArray(interface C)

This only looks at the interfaces that are the directly implemented by the class of the instance passed in, but could be extended to recursively look up the inheritance hierarchy.

Ben Lings
This looks an awful lot like my answer + a bit of boilerplate :)
Kevin Wright
@Kevin - the date stamps say that your answer looks an awful lot like my answer... :-P
Ben Lings
That's not what I see when I order by "newest" :)
Kevin Wright
+2  A: 

How about a hybrid of the other answers

abstract trait A //interested in this one
trait B extends A //and this one
trait C extends A //this one too
trait D //don't care about this one though

val x = new A with B with D
x.getClass.getInterfaces.filter(classOf[A].isAssignableFrom(_))

returns

Array[java.lang.Class[_]] = Array(interface A, interface B)
Kevin Wright