如何在Kotlin中为genric Number分配零?

dm7nw8vv  于 2023-06-24  发布在  Kotlin
关注(0)|答案(4)|浏览(144)

我是Kotlin的新手,我试图编写一个简单的泛型方法,但它无法编译

inline fun <T:Number> List<T>.firstOrZero() : T {
    if (isEmpty())
        return 0   // this line doesn't compile
    else
        return this[0]
}

有办法吗?

xjreopfe

xjreopfe1#

您需要为您想要支持的每个Number子类处理它。比如像这样

inline fun <reified T : Number> List<T>.firstOrZero(): T {
    return (if (isEmpty()) when (T::class) {
        Int::class -> 0
        Double::class -> 0.0
        Float::class -> 0f
        BigInteger::class -> BigInteger.ZERO
        else -> throw RuntimeException()
    }
    else
        this[0]) as T
}
dfuffjeb

dfuffjeb2#

我们无法在Kotlin中以完全通用的方式处理这种情况。无论我们选择什么解决方案,我们都必须分别处理每种类型的Number
因此,我建议不要使用泛型函数,而是使用多个重载:

fun List<Int>.firstOrZero() = if (isEmpty()) 0 else this[0]
fun List<Long>.firstOrZero() = if (isEmpty()) 0 else this[0]

这可能比使用反射的泛型解决方案更快,因为类型是在编译时而不是运行时解析的。
如果你有更多这样的病例,你的病例就更复杂,等等如果你担心代码重复,你可以内联通用代码:

fun List<Int>.firstOrZero() = firstOrDefault { 0 }
fun List<Long>.firstOrZero() = firstOrDefault { 0 }

private inline fun <T:Number> List<T>.firstOrDefault(default: () -> T) : T {
    if (isEmpty())
        return default()
    else
        return this[0]
}

但对于firstOrZero()的具体情况,我认为这是一个矫枉过正。

zpgglvta

zpgglvta3#

您需要确保返回类型与预期类型匹配。
因为定义了泛型类型'T',所以需要返回'T',它扩展了'Number'。

inline fun <T : Number> List<T>.firstOrZero(): T {
    if (isEmpty())
        return 0 as T
    else
        return this[0]
}
4bbkushb

4bbkushb4#

有一种方法可以做到这一点。可以使用default关键字为T类型参数提供默认值。在这种情况下,默认值为0。下面的代码将编译并运行:

inline fun <T:Number> List<T>.firstOrZero() : T {
    if (isEmpty())
        return 0.default<T>()   // this line compiles
    else
        return this[0]
}

default关键字可用于为任何类型参数提供默认值。当您要确保方法或属性始终具有值时,即使未指定类型参数,这也很有用。
在这种情况下,default关键字用于为T类型参数提供默认值0。这意味着如果没有指定T类型参数,则该方法将返回0。
下面是如何使用firstOrZero()方法的示例:

val list = listOf(1, 2, 3)
val firstNumber = list.firstOrZero()
println(firstNumber) // prints 1

val emptyList = emptyList<Int>()
val firstNumberInEmptyList = emptyList.firstOrZero()
println(firstNumberInEmptyList) // prints 0

相关问题