2016-03-13 26 views
6

Próbuję przedłużyć klas enum typu String z następujących funkcji, ale jestem w stanie użyć go w miejscu połączenia tak:Kotlin: Jak rozszerzenie klasy enum z funkcją przedłużacza

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

Co ja tu robię źle?

Odpowiedz

10

proponuję następujące rozwiązanie:

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

Zamiast dołączać funkcję rozszerzenia do klasy, podłączyłem ją do KotlinClass.

Teraz możesz po prostu użyć go: odpowiedź

enum class Test {ONE, TWO, THREE } 

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

Dobra rozmowa, jestem stosunkowo nowa w Kotlin i zapomniałem o KClass – geg

3

będę przepisać dołączyć lekko tak asterisk:

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

Następnie, zakładając swój MyStringEnum jest zdefiniowany następująco:

enum class MyStringEnum { FOO, BAR, BAZ } 

można nazwać to tak:

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

, aby uzyskać wyjście "FOO, BAR, BAZ"

Ponieważ definiujesz join na Class, potrzebujesz rzeczywistego obiektu Class, aby go wywołać. Klasy Enum najwyraźniej nie działają tak, ale jego zdefiniowane wyliczenia mogą dać klasę z javaClass. Więc to jest najlepsze, co mogę wymyślić, że myślę, że spotyka się z ogólnym duchem twojej prośby. Nie wiem, czy istnieje bardziej elegancki sposób na osiągnięcie tego, co próbujesz zrobić dla wszystkich klas wyliczeniowych takich jak ta.

EDIT: Można to dokręcić trochę więcej z tego:

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

który pozwala nazwać tak:

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

Aha, przeniosłeś mnie we właściwym kierunku. Po prostu wypróbowałem 'MyStringEnum :: class.java.join()' bez żadnych skarg. – geg

3

@IRus' jest poprawna, ale nie trzeba użyć refleksji. Dla każdej klasy wyliczeniowej metoda values() jest automatycznie generowana przez kompilator. Ta metoda zwraca tablicę zawierającą wszystkie wpisy. Możemy sprawić, że funkcja rozszerzenie działają bezpośrednio na tej tablicy tak:

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

i nazwać tak:

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