【问题标题】:How do I avoid object expressions for functions that return a SAM interface如何避免返回 SAM 接口的函数的对象表达式
【发布时间】:2016-06-22 19:09:36
【问题描述】:

我是 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) }
}

kotlin 然后说:

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 中使用高阶函数进行编程的博客/演示文稿,我们将不胜感激。

【问题讨论】:

  • Kotlin 选择支持隐式 SAM 接口转换为仅适用于 Java 接口的函数。不适用于 Kotlin 接口。我同意这在某些情况下会损害可读性。类型别名将出现在下一个版本(AFAIR)中。然后 JetBrains 将查看这是否解决了是否应允许转换 Kotlin 接口的问题。有一个功能请求:youtrack.jetbrains.com/issue/KT-7770。同时,我只会在签名中使用(T) -&gt; Boolean。希望使用类型别名重构代码不会太难。

标签: kotlin higher-order-functions


【解决方案1】:

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

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
}

【讨论】:

  • 感谢您的想法。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-30
    • 2021-12-27
    • 2011-02-10
    • 2011-08-17
    • 2013-03-06
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多