我如何获得一个特征来了解它在Scala中的子类的成员?

时间:2015-11-12 13:32:43

标签: scala

我正在尝试找到对象的所有内部案例类,它扩展了特征(MyTrait),但它是不工作如果我拥有ChildClassesObject object 中的所有代码,则以下代码有效,但这不是我想要的,因为我希望所有对象扩展MyTrait以继承childClasses VAL

trait MyTrait {
  import scala.reflect.runtime.universe._
  val childClasses = typeOf[this.type].members.filter(_.isClass)
}

object ChildClassesObject extends MyTrait with App {
  case class User(name: String)
  case class Product(name: String)
  childClasses foreach println
}

我也尝试过使用一个伴随对象,然后将ChildClassesObject的类型传递给MyTrait,但仍然不起作用。

trait MyTrait[T] {
  import scala.reflect.runtime.universe._
  def childClasses(implicit tag: TypeTag[T]) = typeOf[T].members.filter(_.isClass)
}

object ChildClassesObject extends App {
  def apply() = new ChildClassesObject
}

class ChildClassesObject extends MyTrait[ChildClassesObject.type] {
  case class User(name: String)
  case class Product(name: String)
  childClasses foreach println
}

我尝试过一些东西,但是我没有想出任何作品,到目前为止我还没有运气。有人可以告诉我这是如何实现的吗?

2 个答案:

答案 0 :(得分:2)

在您的代码中,trait MyTrait { import scala.reflect.runtime.universe._ val childClasses = typeOf[this.type].members.filter(_.isClass) } 在编译MyTrait期间被填充,因此childClasses将始终为空列表。

scala> trait MyTrait{
   val innerClasses = this.getClass.getClasses
 }

scala> object ChildClassesObject extends MyTrait with App {
  |     case class User(name: String)
  |     case class Product(name: String)
  | }
defined object ChildClassesObject

scala> ChildClassesObject.innerClasses
res9: Array[Class[_]] = Array(class ChildClassesObject$User, class ChildClassesObject$User$, class ChildClassesObject$Product, class ChildClassesObject$Product$, class ChildClassesObject$delayedInit$body)

您可以尝试使用java反射:

this.getClass.getClasses.filter(!_.isSynthetic)

但这样你就能看到合成的内部类。您可以尝试过滤它们:{{1}}

答案 1 :(得分:2)

如果您将extends MyTrait[ChildClassesObject.type]替换为extends MyTrait[ChildClassesObject],则第二个版本有效。

我能够通过使用类型成员而不是类型参数来使您的第一个版本工作:

trait MyTrait {
  type T
  def childClasses(implicit tag: TypeTag[T]) =
    typeOf[T].members.filter(_.isClass)
}

object ChildClassesObject extends MyTrait {
  type T = this.type
  case class User(name: String)
  case class Product(name: String)
}

也许有更好的解决方案;我只是摸索着。