我想为List
实施累积和方法,这样的函数应该接受List<Int>
,List<Float>
等。
我可以说它应该接受List<anything that implements add>
但我认为没有办法在官方文件中指明这一点。
我尝试使用Number
类型,但它显然不起作用。
我应该如何制作一个通用扩展函数来接受任何实现add
等特定方法的类型?
答案 0 :(得分:4)
数字只有以下方法:
public abstract fun toDouble(): Double
public abstract fun toFloat(): Float
public abstract fun toLong(): Long
public abstract fun toInt(): Int
public abstract fun toChar(): Char
public abstract fun toShort(): Short
public abstract fun toByte(): Byte
没有添加,因此您无法将它们添加到一起
typealias Adder<T> = (T)->T
fun <T: Number> T.toAdder(): Adder<T> {
return when(this) {
is Long -> {{it -> (this as Long + it as Long) as T}}
is Int -> {{it -> (this as Int + it as Int) as T}}
is Double -> {{it -> (this as Double + it as Double) as T}}
else -> throw AssertionError()
}
}
fun <T: Number> List<T>.mySum(zero: T): T {
return map { it.toAdder() }.fold(zero) { acc, func -> func(acc) }
}
fun main(args: Array<String>) {
val total = listOf(1,2,4).mySum(0)
}
这样可行,但它使用了大量的转换,应该避免使用
答案 1 :(得分:2)
在Kotlin中,你在stdlib中有这些扩展函数:
fun Iterable<Byte>.sum(): Int { /* compiled code */ }
fun Iterable<Double>.sum(): Double { /* compiled code */ }
fun Iterable<Float>.sum(): Float { /* compiled code */ }
fun Iterable<Int>.sum(): Int { /* compiled code */ }
fun Iterable<Long>.sum(): Long { /* compiled code */ }
fun Iterable<Short>.sum(): Int { /* compiled code */ }
inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int { /* compiled code */ }
inline fun <T> Iterable<T>.sumByDouble(selector: (T) -> Double): Double { /* compiled code */ }
从中您可以看出,没有办法为“List
类型的plus
类型”编写函数,因为Kotlin不是鸭子类型。
另外,您提到List<anything that implements add>
,其中不清楚(或清楚但不正确),因为在Kotlin中,所有数字类型都有plus
而不是add
。从中你可以知道,不同的类有自己的“添加”操作的定义,这种操作在不同的情况下有不同的名称。
我建议您使用名为reduce
或reduceRight
,fold
或foldRight
的功能,它允许您通过传递自定义“添加”操作一个论点。
同样,sum
List<Int>
的实施基本上是:
fun List<Int>.sum() = fold(0, Int::plus)
之类的。
答案 2 :(得分:1)
在其他语言中有一个解决方案(Haskell和Scala是最着名的),最终可能会在Kotlin中添加:类型类。有关(非最终)提案,请将https://github.com/Kotlin/KEEP/pull/87添加到Kotlin。
在添加它们之前,您可以手动执行类似操作:
interface Adder<T> {
fun add(x: T, y: T): T
}
object IntAdder : Adder<Int> {
fun add(x: Int, y: Int): Int = x + y
}
// similar for other types
// definition of cumulativeSum
fun <T> cumulativeSum(list: List<T>, adder: Adder<T>): List<T> = ...
// call
cumulativeSum(listOf(1,2,3), IntAdder)
部分类型类解决的是您不需要手动传递adder
参数,而编译器将根据T
确定它。