2010-11-21 178 views
4

如何使用反射获取对象中的所有对象?如何通过混合特性与反射来访问对象内的对象?

考虑以下代码:

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!" 

我想有一个特质(MyEnum),我可以混合到被检体保持我的“枚举对象”与方法,以回报他们的(def values: List[MonthDay])的列表或者iterate (def next: MonthDaydef previous: MonthDay没有重复自己几次(这是绝对至关重要!)。

想法是values访问MonthDay对象,并找到它们正在扩展的类的所有单例对象(MonthDay)和反射。类似

回答

1

我的解决方案,基于Landei's answer是:

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

我不认为你应该再调用这个MyEnum,因为一个枚举类型意味着一个封闭的价值观。

(如果枚举值定义为object s不工作)

+0

这看起来非常有趣!这可能是一种值得使用的方法,直到真正的解决方案工作('getClass.getDeclaredClasses',目前不工作,看到这个错误报告:http://lampsvn.epfl.ch/trac/scala/ticket/4023) – soc 2010-11-23 01:24:36

+0

当然,我我可以开一个更好的名字,你有什么想法吗? – soc 2010-11-23 01:25:52

+0

@soc:也许'FindContainedVals' – 2010-11-23 01:27:35

1
+0

我已经尝试过这样做,但我不能看清物体/场/方法,如果我看着MonthDay.MODULE $。 – soc 2010-11-21 21:19:01

+0

@soc:他指的是'val methods = getClass.getMethods过滤器(m => m.getParameterTypes.isEmpty && classOf [Value] .isAssignableFrom(m.getReturnType))'它使用普通的Java反射来查找返回正确类型的无参数函数,并假定每个函数都是一个Enumeration值。我想象有一天,当我们有真正的* Scala *反射时,我们将能够判断这些方法是用'object','val'还是'def'创建的(以排除'def's)。 (即使你将对象声明为'object',这个方法也应该可以工作) – 2010-11-23 00:25:36

+0

他还提到了m.invoke(),它将'methods'变成'values'。 – 2010-11-23 00:48:22

0

您应该能够使用现有的预斯卡拉Enumeration类:http://www.scala-lang.org/api/current/scala/Enumeration.html

它似乎非常接近你的使用情况!

+0

不是,它不能扩展为提供用户特定的额外实例,因为OP请求 – 2010-11-21 20:26:00

+0

使用'Enumeration',用户不能创建他自己的'MonthDays'。 – 2010-11-23 01:14:00