使用反射获取在 Scala 中实现特征的所有 类
Get all the classes that implements a trait in Scala using reflection
我想列出所有实现特定特征的案例 类。我目前正在使用 Clapper ClassUtil 来做到这一点。我能够得到直接实现特征的案例 类。但是,我无法获得未直接实现该特征的其他 类。我怎样才能得到所有直接或间接实现特征的 类 。 ?
val finder = ClassFinder()
finder.getClasses().filter(_.isConcrete).filter(_.implements("com.myapp.MyTrait"))
Scala 版本:2.11
Clapper Class 实用版本: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
,我应该能够同时获得 Department
和 User
,因为它们都直接或间接实现了 NamedEntity。使用 implements
方法,它只会给用户。我也尝试使用 interfaces
方法,它也将提供直接超级 类 only.
查看 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
}
}
ClassUtil 现在contains this functionality(v1.4.0,也许还有更早的版本):
val finder = ClassFinder()
val impl = ClassFinder.concreteSubclasses("foo.NamedEntity", finder.getClasses())
我想列出所有实现特定特征的案例 类。我目前正在使用 Clapper ClassUtil 来做到这一点。我能够得到直接实现特征的案例 类。但是,我无法获得未直接实现该特征的其他 类。我怎样才能得到所有直接或间接实现特征的 类 。 ?
val finder = ClassFinder()
finder.getClasses().filter(_.isConcrete).filter(_.implements("com.myapp.MyTrait"))
Scala 版本:2.11
Clapper Class 实用版本: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
,我应该能够同时获得 Department
和 User
,因为它们都直接或间接实现了 NamedEntity。使用 implements
方法,它只会给用户。我也尝试使用 interfaces
方法,它也将提供直接超级 类 only.
查看 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
}
}
ClassUtil 现在contains this functionality(v1.4.0,也许还有更早的版本):
val finder = ClassFinder()
val impl = ClassFinder.concreteSubclasses("foo.NamedEntity", finder.getClasses())