如何避免返回SAM接口的函数的对象表达式

时间:2016-06-22 19:09:36

标签: kotlin higher-order-functions

我是一个kotlin新手,所以这可能是微不足道的,但我没有在kotlinlang.org找到任何相关的帮助。

为了学习kotlin,我想实现PushStream库。

我想定义类似这样的基本类型:

typealias Receiver<T>   = (T) -> bool
typealias PushStream<T> = (Receiver<T>) -> Unit

不支持AFAIK类型别名,因此上面只是伪代码。

所以我的第一次尝试是这样的:

interface Receiver<T> : (T) -> Boolean {
}

interface PushStream<T> : (Receiver<T>) -> Unit {
}

fun <T> singleton (v : T) : PushStream<T> {
    return { r : Receiver<T> -> r (v) }
}
然后科特林说:

Error:(10, 12) Kotlin: Type mismatch: inferred type is (Receiver<T>) -> Boolean but PushStream<T> was expected

我似乎能够解决它:

fun <T> singleton (v : T) : (Receiver<T>) -> Unit {
    return { r : Receiver<T> -> r (v) }
}

但这不是我想要的签名,特别是对于我可能需要指定完整函数类型的更高级的运算符:

fun <T> singleton (v : T) : ((T) -> Boolean) -> Unit {
    return { r : Receiver<T> -> r (v) }
}

我认为这使得API难以阅读。

我能做的是使用对象表达式:

fun <T> singleton (v : T) : PushStream<T> {
    return object : PushStream<T> {
        operator override fun invoke (r : Receiver<T>) : Unit {
            r (v)
        }
    }
}

这有效,但我想使用Lambda表达式来保持代码更简洁。

欢迎任何提示。此外,如果您知道任何有关kotlin中高阶函数编程的有趣博客/演示文稿,也会非常感激。

2 个答案:

答案 0 :(得分:2)

由于尚未存在类型别名,因此类型签名不能相互替换。在您的情况下,您需要使用组合而不是继承来创建抽象级别:

open class Receiver<T>(val op: (T) -> Boolean)

open class PushStream<T>(val op: (Receiver<T>) -> Unit)

fun <T> singleton (v: T): PushStream<T> {
    return PushStream<T> { r -> r.op(v) }
}

我用类替换了接口,因为我没有看到其余的代码。如果需要接口,请使用工厂函数:

interface Receiver<T> {
    val op: (T) -> Boolean
}

fun <T> receiver(op: (T) -> Boolean) = object : Receiver<T> {
    override val op = op
}

答案 1 :(得分:1)

如果在java中定义PushStream-Interface,可以像这样使用它:

fun <T> singleton (v : T) : PushStream<T> {
    return PushStream { r : Receiver<T> -> r (v) }
}