Kotlin 接口函数作为表达式主体

Ben*_*aci 0 interface kotlin

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

在此处输入图片说明

选择这样做时,kotlin 会将函数转换为表达式主体:

在此处输入图片说明

有没有办法要求一个接口(就像这个函数覆盖的那个)?

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

我知道我可以通过使用 aabstract 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))
}
Run Code Online (Sandbox Code Playgroud)

这样一个继承类将能够覆盖该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
}

Run Code Online (Sandbox Code Playgroud)

Ten*_*r04 5

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

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

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

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