使用反射在Scala中获取所有实现某个trait的类

9

我想列出所有实现特定trait的case class。我目前正在使用Clapper ClassUtil来做这件事。我能够获取直接实现trait的case class。然而,我无法获取未直接实现trait的其他类。如何获取所有直接或间接实现trait的类?

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

Scala版本: 2.11

Clapper Class Util版本: 1.0.6

是否有其他方式可以获取这些信息?有人能指点我正确的方向吗? 我尝试使用scala.reflect,但无法理解如何获取信息。

EDIT:

样例特征和用途:

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

现在,如果我将特征设为NamedEntity,我应该能够获取DepartmentUser,因为它们都直接或间接实现了NamedEntity。使用implements方法,只会给出User。我还尝试使用interfaces方法,这也只提供直接的超类。

你能定义三个特征/类及其关系以演示问题吗? - 0__
我已经添加了示例特征和案例类用法。 - Yadu Krishnan
2个回答

4

源代码来看,问题似乎在于它没有遵循接口层次结构。如果你这样做,你会发现所有实例:

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

3

现在,ClassUtil(版本1.4.0,可能也适用于早期版本)包含了这个功能

val finder = ClassFinder()
val impl = ClassFinder.concreteSubclasses("foo.NamedEntity", finder.getClasses())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接