【问题标题】:Get all the classes that implements a trait in Scala using reflection使用反射获取在 Scala 中实现特征的所有类
【发布时间】:2015-12-30 13:41:19
【问题描述】:

我想列出所有实现特定特征的案例类。我目前正在使用Clapper ClassUtil 来执行此操作。我能够获得直接实现特征的案例类。但是,我无法获得不直接实现该特征的其他类。如何获得所有直接或间接实现特征的类。 ?

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

Scala 版本:2.11

Clapper 类实用程序版本: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

现在,如果我将 trait 指定为 NamedEntity,我应该能够同时获得 DepartmentUser,因为它们都直接或间接地实现了 NamedEntity。使用implements 方法,它只会给用户。我也尝试使用interfaces 方法,它也只提供直接超类。

【问题讨论】:

  • 您能否定义三个特征/类及其关系来说明问题?
  • 我已经添加了示例特征和案例类用法。

标签: scala reflection traits


【解决方案1】:

查看source code,问题似乎在于它不遵循接口层次结构。如果你这样做,你会找到所有实例:

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

【讨论】:

    【解决方案2】:

    ClassUtil now contains this functionality (v1.4.0, 也可能在早期版本中):

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-08
      • 2021-05-13
      • 1970-01-01
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多