在Kotlin中使用功能类型的功能接口
从Kotlin调用Java代码时,有SAM转换,以便Java代码如下所示:
adapter.setOnClickListener(new OnClickListener() { @Override public void onClick(View view, int position) { // Do stuff here } });
可以看起来像这样:
adapter.setOnClickListener { view, position -> // Do stuff }
现在,我正在做一个Kotlin项目,我想将一个函数接口定义为一个事件监听器:
interface OnSomeActionListener { fun onSomeAction(parameter1: Int, parameter2: String) }
在SomeClass
我有一个函数来设置监听器:
... private var onSomeActionListener: OnSomeActionListener? = null fun setOnSomeActionListener(listener: OnSomeActionListener) { onSomeActionListener = listener } ...
当我创建这个类的实例并尝试调用setter函数时,我这样做:
val thing = SomeClass() thing.setOnSomeActionListener(object : OnSomeActionListener { override fun onSomeAction(parameter1: Int, parameter2: String) { // Do stuff here } })
我知道Kotlin具有函数类型,因此不支持来自诸如此类的各个站点的SAM转换。
我已经读了一些关于函数类型的内容,但是我之前没有使用它们。
我将如何重写我的代码,以便我可以像这样调用setter函数?
val thing = SomeClass() thing.setOnSomeActionListener { parameter1, parameter2 -> // Do stuff here }
。
函数类型如下所示:
(Parameters) -> ReturnType
在你的情况下,而不是使用接口类型,你可以使用(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) }
添加名称
在功能类型中,您还可以指定参数的名称。 这在引擎盖下并没有太大改变,但有时候可以自动完成,这真的很棒。
(view: View, position: Int) -> Unit
使用类型别名
为了避免每次都输入(View, Int) -> Unit
,你可以定义一个typealias:
typealias OnSomeActionListener = (view: View, position: Int) -> Unit
所以你的元素现在看起来像这样:
private var onSomeActionListener: OnSomeActionListener? = null fun setOnSomeActionListener(listener: OnSomeActionListener) { onSomeActionListener = listener }
…
val thing = SomeClass() thing.setOnSomeActionListener { view, position -> // Do stuff here }
那么,这样的事情:
// declare a variable of nullable function type: var onSomeActionListener: ((Int, String) -> Unit)? = null // declare higher-order function: fun setOnSomeActionListener(listener: (Int, String) -> Unit) { onSomeActionListener = listener } // set listener: val listener: (Int, String) -> Unit = { p1, p2 -> { /* some stuff */ } } setOnSomeActionListener(listener) // or in one line: setOnSomeActionListener { p1, p2 -> { /* some stuff */ } }
更多信息: 高阶函数和Lambda
定义接受函数并返回接口的函数怎么样?
fun makeOnSomeActionListener(f: (Int,String) -> Unit) = object : OnSomeActionListener { override fun onSomeAction(parameter1: Int, parameter2: String) = f(parameter1, parameter2) }
接口将其工作委托给f
。
那么你可以写
val thing = SomeClass() thing.setOnSomeActionListener(makeOnSomeActionLisener { parameter1, parameter2 -> // Do stuff here })