首页 > 解决方案 > Kotlin 接口函数作为表达式主体

问题描述

当在 Kotlin 中编写一个函数时,它基本上是在一个Thread创建内部完全实现的start(),Android Studio 提供了“转换为表达式主体”的选项

在此处输入图像描述

选择这样做时,Kotlin将功能转换为表达式主体:

在此处输入图像描述

有没有办法要求这个接口(比如这个函数覆盖的那个)?

我希望接口始终要求validate函数启动一个新的Thread并且只有(!!)能够执行 that 里面的东西Thread,而不是方法体本身,因为它只会用于寻址服务器。

abstract class我知道我可以通过使用一个而不是这样的来强制这种行为interface

abstract class ServerValidator<T> {
    fun validate(value: T?, function: ((ValidationResult) -> Unit)) = Thread {
        doValidation(value, function)
    }.start()

    protected abstract fun doValidation(value: T?, function: ((ValidationResult) -> Unit))
}

这样一个继承类将能够覆盖该doValidation函数,而另一个类只能调用validate并因此总是使用一个新线程。

但是,我特别想知道是否可以用接口做这样的事情。

就像是:

interface ServerValidator<T> {
    fun validate(value: T?, function: ((ValidationResult) -> Unit)) = Thread::start
}

// or 

interface ServerValidator<T> {
    fun validate(value: T?, function: ((ValidationResult) -> Unit)) : Thread::start
}

标签: kotlininterface

解决方案


表达式主体与函数签名无关。它纯粹是一种语法替代方案。在您的示例的两种情况下,该函数都返回Unit,因为在表达式主体情况下,它返回的是Thread.start()返回的内容,即Unit.

我认为您实际上要问的是您是否不仅可以定义函数返回的内容,还可以定义它如何获得该结果的中间步骤,即强制它在后台线程上执行某些操作。答案是否定的。语言中没有任何东西可以定义这样的结构。

您已经描述了正确的方法,即采用函数参数,然后接收类可以自己在后台线程中调用它。

另一种方法可能是将函数定义为suspend函数,这意味着它不应该在不使用适当的协程 Dispatcher 来执行阻塞代码的情况下执行阻塞代码。然后,如果实现接口函数的人未能使用后台调度程序,他们就违反了suspend函数应该如何工作的约定。但是编译器仍然不会强迫他们正确地做到这一点。


推荐阅读