2016-03-13 17 views
6

Sto cercando di estendere le classi di tipo enum String con la seguente funzione, ma sono in grado di utilizzarlo al luogo di chiamata in questo modo:Kotlin: come estendere la classe enum con una funzione di estensione

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

Cosa sto facendo di sbagliato qui?

risposta

10

Suggerisco seguente soluzione:

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

Invece di collegare la funzione di estensione a Class, l'ho collegata a KotlinClass.

Ora, si può semplicemente utilizzare: risposta

enum class Test {ONE, TWO, THREE } 

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

Buona chiamata, sono relativamente nuovo a Kotlin e mi sono dimenticato di KClass – geg

3

lo riscrivo vostro ci uniamo un po 'come questo con un jolly:

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

Quindi, supponendo che il MyStringEnum è definita in questo modo:

enum class MyStringEnum { FOO, BAR, BAZ } 

si può chiamare in questo modo:

per ottenere uscita "FOO, BAR, BAZ"

Poiché si sta definendo join su Class, è necessario un oggetto Class effettivo per chiamarlo. Apparentemente le classi Enum non funzionano in questo modo, ma le enumerazioni definite possono generare una classe con javaClass. Quindi questo è il meglio che ho potuto trovare e penso che soddisfi lo spirito generale della tua richiesta. Non so se c'è un modo più elegante per ottenere ciò che stai cercando di fare per tutte le classi enum come questa.

EDIT: Si può stringere questo un po 'di più con questo:

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

che consente di chiamare in questo modo:

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

Ah, mi è stato spostato nella giusta direzione. Ho appena provato 'MyStringEnum :: class.java.join()' senza lamentele. – geg

3

@IRus' è corretto, ma non si deve utilizzare la riflessione. Per ogni classe enum, un metodo values() viene generato automaticamente dal compilatore. Questo metodo restituisce una matrice contenente tutte le voci. Possiamo fare la funzione di estensione operare direttamente su questo array come questo:

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

E chiamare in questo modo:

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