Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all the classes that implements a trait in Scala using reflection

I want to list out all the case classes which implements a particular trait. I am currently using Clapper ClassUtil for doing that. I am able to get the case classes that are directly implementing a trait. However, I am not able to get the other classes which are not directly implementing the trait. How can I get all classes which directly or indirectly implements a trait. ?

val finder = ClassFinder()
finder.getClasses().filter(_.isConcrete).filter(_.implements("com.myapp.MyTrait"))

Scala Version : 2.11

Clapper Class Util Version : 1.0.6

Is there any other way I can get these information? Can someone point me to the right direction? I tried using scala.reflect but could not understand how to get the info.

EDIT:

Sample traits and usages:

trait BaseEntity
trait NamedEntity{ val name:String}
trait MasterDataEntity extends NamedEntity

case class Department(id:Long, override val name:String) extends MasterDataEntity
case class Employee(id:Long, name:String) extends BaseEntity
case class User(id:Long, override val name:String) extends NamedEntity

Now, if I give the trait as NamedEntity, I should be able to get both Department and User since they both are directly or indirectly implementing NamedEntity. With implements method, it will give only User. I also tried by using interfaces method, which will also provide the direct super classes only.

like image 343
Yadu Krishnan Avatar asked Dec 30 '15 13:12

Yadu Krishnan


People also ask

How do you implement a trait in Scala?

In Scala, we are allowed to implement the method(only abstract methods) in traits. If a trait contains method implementation, then the class which extends this trait need not implement the method which already implemented in a trait. As shown in the below example. Traits does not contain constructor parameters.

What is Scala reflection?

Scala reflection enables a form of metaprogramming which makes it possible for programs to modify themselves at compile time. This compile-time reflection is realized in the form of macros, which provide the ability to execute methods that manipulate abstract syntax trees at compile-time.

Can a object inherit a trait in Scala?

Unlike a class, Scala traits cannot be instantiated and have no arguments or parameters. However, you can inherit (extend) them using classes and objects.

Can Scala traits have methods?

In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods. A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait.


1 Answers

Looking at the source code, the problem seems to be that it doesn't follow the interfaces hierarchy. If you do that, you find all instances:

package foo

import java.io.File

import org.clapper.classutil.{ClassFinder, ClassInfo}

object Main extends App {
  val jar     = new File("target/scala-2.11/class_test_2.11-0.1.0.jar")
  val finder  = ClassFinder(jar :: Nil)
  val classes = ClassFinder.classInfoMap(finder.getClasses().iterator)
  val impl    = find("foo.NamedEntity", classes)
  impl.foreach(println)

  def find(ancestor: String, classes: Map[String, ClassInfo]): List[ClassInfo] =
    classes.get(ancestor).fold(List.empty[ClassInfo]) { ancestorInfo =>
      val ancestorName = ancestorInfo.name

      def compare(info: ClassInfo): Boolean =
        info.name == ancestorName ||
        (info.superClassName :: info.interfaces).exists {
          n => classes.get(n).exists(compare)
        }

      val it = classes.valuesIterator
      it.filter { info => info.isConcrete && compare(info) } .toList
    }
}
like image 66
0__ Avatar answered Nov 06 '22 02:11

0__