在Kotlin中使用功能类型的功能接口

Far*_*deh 6 java lambda higher-order-functions kotlin kotlin-interop

从Kotlin调用Java代码时,有SAM转换,因此Java代码如下:

adapter.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view, int position) {
        // Do stuff here
    }
});
Run Code Online (Sandbox Code Playgroud)

可以这样:

adapter.setOnClickListener { view, position ->
    // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

现在,我正在研究Kotlin项目,我想将功能接口定义为事件监听器:

interface OnSomeActionListener {

    fun onSomeAction(parameter1: Int, parameter2: String)

}
Run Code Online (Sandbox Code Playgroud)

SomeClass我有一个函数来设置监听器:

    ...

    private var onSomeActionListener: OnSomeActionListener? = null

    fun setOnSomeActionListener(listener: OnSomeActionListener) {
        onSomeActionListener = listener
    }

    ...
Run Code Online (Sandbox Code Playgroud)

当我创建这个类的实例并尝试调用setter函数时,我这样做:

val thing = SomeClass()

thing.setOnSomeActionListener(object : OnSomeActionListener {
    override fun onSomeAction(parameter1: Int, parameter2: String) {
        // Do stuff here
    }
})
Run Code Online (Sandbox Code Playgroud)

我知道,科特林具有函数类型,因此不从不同的网站,如支持SAM转换这一块.

我已经阅读了一些关于函数类型的内容,但我之前没有使用它们.

我如何重写我的代码,以便我可以像这样调用setter函数?

val thing = SomeClass()

thing.setOnSomeActionListener { parameter1, parameter2 ->
    // Do stuff here
}
Run Code Online (Sandbox Code Playgroud)

.

Rob*_*bCo 12

函数类型如下所示:

(Parameters) -> ReturnType
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可以使用,而不是使用接口类型(View, Int) -> Unit.它看起来像这样:

private var onSomeActionListener: ((View, Int) -> Unit)? = null

fun setOnSomeActionListener(listener: (View, Int) -> Unit) {
    onSomeActionListener = listener
}

private fun callSomeActionListener(view: View, position: Int) {
    onSomeActionListener?.invoke(view, position)
}
Run Code Online (Sandbox Code Playgroud)

添加名称

在函数类型中,您还可以指定参数的名称.这并没有太大的改变,但它们可以在这里和调用代码中添加一些清晰度,这很好.

(view: View, position: Int) -> Unit
Run Code Online (Sandbox Code Playgroud)

使用类型别名

为避免(View, Int) -> Unit每次都要输入,您可以定义一个typealias:

typealias OnSomeActionListener = (view: View, position: Int) -> Unit
Run Code Online (Sandbox Code Playgroud)

这样你的代码现在又看起来像这样:

private var onSomeActionListener: OnSomeActionListener? = null

fun setOnSomeActionListener(listener: OnSomeActionListener?) {
    onSomeActionListener = listener
}   
Run Code Online (Sandbox Code Playgroud)

并称之为:

val thing = SomeClass()

thing.setOnSomeActionListener { view, position ->
    // Do stuff here
}
Run Code Online (Sandbox Code Playgroud)