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

Kotlin 如何避免返回SAM接口的函数的对象表达式,kotlin,higher-order-functions,Kotlin,Higher Order Functions,我是一个kotlin新手,所以这可能是微不足道的,但我在kotlinlang.org上找不到任何相关的帮助 为了学习一些关于kotlin的知识,我喜欢实现PushStream库 我想定义基本类型如下: typealias Receiver<T> = (T) -> bool typealias PushStream<T> = (Receiver<T>) -> Unit typealias接收器=(T)->bool typealias推流=(接收

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

为了学习一些关于kotlin的知识,我喜欢实现
PushStream

我想定义基本类型如下:

typealias Receiver<T>   = (T) -> bool
typealias PushStream<T> = (Receiver<T>) -> Unit
typealias接收器=(T)->bool
typealias推流=(接收器)->单位
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) }
}
接口接收器:(T)->布尔值{
}
接口PushStream:(接收器)->单元{
}
有趣的单身汉(v:T):PushStream{
返回{r:Receiver->r(v)}
}
科特林接着说:

Error:(10, 12) Kotlin: Type mismatch: inferred type is (Receiver<T>) -> Boolean but PushStream<T> was expected
错误:(10,12)Kotlin:类型不匹配:推断类型为(接收器)->布尔,但应为PushStream
我似乎可以通过以下方式解决问题:

fun <T> singleton (v : T) : (Receiver<T>) -> Unit {
    return { r : Receiver<T> -> r (v) }
}
fun singleton(v:T):(接收器)->单元{
返回{r:Receiver->r(v)}
}
但这不是我想要的签名,特别是对于更高级的运算符,我可能需要指定完整的函数类型:

fun <T> singleton (v : T) : ((T) -> Boolean) -> Unit {
    return { r : Receiver<T> -> r (v) }
}
fun单例(v:T):((T)->布尔)->单位{
返回{r:Receiver->r(v)}
}
我相信这会使API更难阅读

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

fun <T> singleton (v : T) : PushStream<T> {
    return object : PushStream<T> {
        operator override fun invoke (r : Receiver<T>) : Unit {
            r (v)
        }
    }
}
fun singleton(v:T):PushStream{
返回对象:PushStream{
操作员覆盖乐趣调用(r:接收器):单位{
r(v)
}
}
}
这是可行的,但我希望使用Lambda表达式来保持代码更简洁


欢迎任何提示。另外,如果您知道任何关于kotlin中使用高阶函数编程的有趣博客/演示,也将不胜感激。

由于没有类型别名(但),类型签名不能*相互替代。在您的情况下,您需要使用组合而不是继承来创建抽象级别:

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) }
}
开放类接收器(val op:(T)->布尔值)
开放类推流(val op:(接收器)->单元)
有趣的单身汉(v:T):PushStream{
返回推流{r->r.op(v)}
}
我用类替换了接口,因为我看不到其余的代码。如果需要接口,请使用出厂功能:

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

fun <T> receiver(op: (T) -> Boolean) = object : Receiver<T> {
    override val op = op
}
接口接收器{
val op:(T)->布尔值
}
有趣的接收器(op:(T)->布尔)=对象:接收器{
覆盖值op=op
}

如果您用java定义PushStream接口,您可以这样使用它:

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

Kotlin选择支持隐式SAM接口转换为仅用于Java接口的函数。不适用于Kotlin接口。我同意在某些情况下这会损害可读性。类型别名将出现在下一个版本(AFAIR)中。JetBrains随后将查看这是否解决了是否允许转换Kotlin接口的问题。有一个功能请求:。同时,我会在签名中使用
(T)->布尔值。希望用类型别名重构代码不会太难。谢谢你的想法。