2010-11-21 174 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