How to access objects within an object by mixing in a trait with reflection?

混江龙づ霸主 提交于 2019-12-29 01:40:30

问题


How can I get all of the objects within an object with reflection?

Consider this code:

object MonthDay extends MyEnum {
  //Some important holidays
  object NewYear       extends MonthDay( 1,  1)
  object UnityDay      extends MonthDay(11,  9)
  object SaintNicholas extends MonthDay(12,  6)
  object Christmas     extends MonthDay(12, 24)
}

class MonthDay(month: Int, day: Int)

trait MyEnum {
  val values: List[MonthDay] = this.getClass.getField("MODULE$")...
  val next: MonthDay = ...
  val previous: MonthDay = ...
}

//Of course the user can create his own MonthDays
val myBirthDay = new MonthDay(month, day)

if(!MonthDay.values.contains(myBirthDay)) "Well, I probably have to work"
else "Great, it is a holiday!"

I want to have a trait (MyEnum) which I can mix into the object holding my "enumeration objects" with methods to return a list of them (def values: List[MonthDay]) or iterate over them (def next: MonthDay or def previous: MonthDay) without repeating myself a few times (this is absolutely crucial!).

The idea is that values accesses the MonthDay object and finds all singleton objects of the class they are extending (MonthDay) with reflection.


回答1:


My solution, based on Landei's answer would be:

trait MyEnum{
   def valsOfType[T:Manifest] = {
      val c=implicitly[Manifest[T]].erasure
      for {m <- getClass.getMethods 
           if m.getParameterTypes.isEmpty && c.isAssignableFrom(m.getReturnType)
      } yield (m.invoke(this).asInstanceOf[T])
   }
}

class MonthDay(month:Int,day:Int)

object MonthDay extends MyEnum {
   //maybe you want to call this "holidays" instead
   lazy val values = valsOfType[MonthDay] 

   val NewYear       = new MonthDay( 1,  1)
   val UnityDay      = new MonthDay(11,  9)
   val SaintNicholas = new MonthDay(12,  6)
   val Christmas     = new MonthDay(12, 24)
}

I don't think you should call this MyEnum anymore, because an enumerated type implies a closed set of values.

(Doesn't work if the enumeration values are defined as objects)




回答2:


Something similar is done in Enumeration.populateNameMap: https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_8_1_final/src/library/scala/Enumeration.scala




回答3:


You should be able to use the pre-existing Scala Enumeration class: http://www.scala-lang.org/api/current/scala/Enumeration.html

It seems to come very close to your use-case!



来源:https://stackoverflow.com/questions/4239594/how-to-access-objects-within-an-object-by-mixing-in-a-trait-with-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!