在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 })