嗯,艱難的一個。我有一個工作解決方案,但我覺得它很難看。我會對任何更優雅的方法感興趣!
def enumValueOf[T <: Enum[T]](cls: Class[_], stringValue: String): Enum[_] =
Enum.valueOf(cls.asInstanceOf[Class[T]], stringValue).asInstanceOf[Enum[_]]
val value = paramClass match {
case _ if classOf[Enum[_]].isAssignableFrom(paramClass) => enumValueOf(paramClass, "MYENUM")
case _ => // other cases
}
爲什麼我認爲我們需要這種複雜性的原因...
我們需要編譯器相信我們有Class[_]
實際上是一個Class[T <: Enum[T]]
(所以當然,經初步測試,這確實是Java枚舉 - 就像你的代碼中所做的那樣)。所以我們將cls
轉換爲Class[T]
,其中T
被編譯器推斷爲<: Enum[T]
。但編譯器仍然需要找到合適的T
,並且在這裏默認爲Nothing
。所以,就編譯器而言,cls.asInstanceOf[Class[T]]
是Class[Nothing]
。這是暫時確定,因爲它可以用於呼叫Enum.valueOf
- 問題是推斷的返回類型valueOf
當然也是Nothing
。在這裏我們遇到了一個問題,因爲當我們試圖實際使用Nothing
類型的實例時,編譯器會插入一個異常。因此,我們最終將valueOf
的返回值轉換爲Enum[_]
。
然後總是讓編譯器推斷出類型參數爲enumValueOf
,並且從不試圖自己指定它(因爲我們不應該知道它) - 並因此以另一種方法提取對Enum.valueOf
的調用,給編譯器一個綁定T <: Enum[T]
的機會。
正如我所說的,我不是很滿意這個解決方案,它看起來方式複雜得多,它應該是...
更新:我稍微簡化了代碼。