2017-02-17 52 views
2

我寫了一個Kotlin擴展,它爲枚舉值添加next()。但是有沒有更好的方法來做到這一點?Kotlin擴展爲下一個枚舉值沒有反射

fun <T : Enum<*>> T.next(): T { 
    val values = this::class.java.getEnumConstants() 
    return if (this.ordinal < values.size - 1) 
      values[this.ordinal + 1] 
     else 
      values[0] 
} 
enum class Color {Red, Yellow, Green} 
Color.Red.next() //Yellow 
  1. 我能做到,沒有思考?
  2. 如果沒有,如何用Kotlins反射做到這一點?

該想法是從枚舉值迭代到下一個。但僅限於特定的值,不適用於整個枚舉values()列表。我想阻止的事情就是把下面的添加到每個枚舉類型:

fun next() = if (this.ordinal == Color.values().size - 1) 
     Color.values()[0] 
    else 
     Color.values()[this.ordinal + 1] 

回答

2

你可以做,沒有反映在科特林1.1使用enumValues<T>()(目前,你可以嘗試the 1.1 RC build),不使用反射裏面,因爲它在呼叫站點被內聯,並且相應的enum類型在編譯時被放置在結果代碼中。例如:

inline fun <reified T: Enum<T>> T.next(): T { 
    val values = enumValues<T>() 
    val nextOrdinal = (ordinal + 1) % values.size 
    return values[nextOrdinal] 
} 

(demo of this code) | inlinereified是必需的,因爲enumValues<T>()具有reified T

與科特林1.0.6作品的另一種(但仍然使用getDeclaringClass()從Java反射):

fun <T: Enum<T>> T.next(): T { 
    val values = declaringClass.enumConstants 
    val nextOrdinal = (ordinal + 1) % values.size 
    return values[nextOrdinal] 
}