2016-03-13 87 views
6

我試圖String類型的枚舉類具有以下功能延伸,但我無法在調用點使用它,像這樣:科特林:如何與擴展功能擴展枚舉類

fun <T: Enum<String>> Class<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String { 
    return this.enumConstants 
     .drop(skipFirst) 
     .dropLast(skipLast) 
     .map { e -> e.name } 
     .joinToString() 
} 

MyStringEnum.join(1, 1); 

我在這裏做錯了什麼?

回答

10

我建議以下解決方案:

fun <T : Enum<*>> KClass<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String { 
    return this.java 
      .enumConstants 
      .drop(skipFirst) 
      .dropLast(skipLast) 
      .map { e -> e.name } 
      .joinToString() 
} 

而不是將附加擴展函數附加到類,我將它附加到KotlinClass。現在

,你可以簡單地使用它:

enum class Test {ONE, TWO, THREE } 

fun main(args: Array<String>) { 
    println(Test::class.join()) 
} 
// ONE, TWO, THREE 
+0

好的電話,我對Kotlin比較陌生,忘記了KClass – geg

3

我會重寫你這樣用通配符稍微加入:

fun <T: Enum<*>> Class<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String { 
    return this.enumConstants 
      .drop(skipFirst) 
      .dropLast(skipLast) 
      .map { e -> e.name } 
      .joinToString() 
} 

然後,假設您的MyStringEnum的定義是這樣的:

enum class MyStringEnum { FOO, BAR, BAZ } 

你可以這樣調用:

println(MyStringEnum.values()[0].javaClass.join()) 

獲得輸出「FOO,BAR,BAZ」

由於您在Class上定義了聯接,因此您需要一個實際的Class對象來調用它。枚舉類顯然不能像那樣工作,但是其定義的枚舉可以產生一個類javaClass。所以這是我能想到的最好的,我認爲符合你的要求的一般精神。我不知道是否有一種更優雅的方式來實現你想爲所有像這樣的枚舉類做什麼。

編輯:

fun Enum<*>.join(skipFirst: Int = 0, skipLast: Int = 0): String { 
    return this.javaClass.join(skipFirst, skipLast) 
} 

,它可以讓你調用這樣的:你可以多一點點這種收緊這件事

println(MyStringEnum.values()[0].join()) 
+0

啊哈,你在正確的方向打動了我。只是嘗試'MyStringEnum :: class.java.join()'沒有任何抱怨。 – geg

3

@IRus'答案是正確的,但你不必使用反射。對於每個枚舉類,編譯器自動生成一個values()方法。此方法返回一個包含所有條目的數組。我們可以擴展功能直接在此數組像這樣進行操作:

fun <T : Enum<*>> Array<T>.join(skipFirst: Int = 0, skipLast: Int = 0) 
     = drop(skipFirst) 
     .dropLast(skipLast) 
     .map { e -> e.name } 
     .joinToString() 

,並調用它是這樣的:

fun main(args: Array<String>) { 
    Test.values().join() 
}