2016-03-13 185 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() 
}