当前位置: 首页 > 知识库问答 >
问题:

在Kotlin中使用具有函数类型的函数接口

柯天宇
2023-03-14

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

我知道静态编程语言有函数类型,因此不支持来自各种站点的SAM转换,例如这个站点。

我读过一些关于函数类型的书,但我以前没有使用过它们。

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

val thing = SomeClass()

thing.setOnSomeActionListener { parameter1, parameter2 ->
    // Do stuff here
}

.

共有3个答案

韦志新
2023-03-14

如何定义接受函数并返回接口的函数?

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
})
公孙芷阳
2023-03-14

是这样的:

// 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

喻渊
2023-03-14

函数类型如下所示:

(Parameters) -> ReturnType

在您的情况下,您可以使用(View, Int)-而不是使用接口类型

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

使用类型别名

避免键入<代码>(视图,Int)-

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
}

 类似资料:
  • 无论我用什么方法尝试,无论是主构造函数还是次构造函数,我都不知道如何在kotlin中声明一个带有超类和构造函数的新类。 这是我最想做的,但它给出了一个错误,期望成员声明。 这是我认为主要构造函数的外观,但它给出了相同的错误。在Internet上搜索没有帮助,我只能找到第二个示例。 那么,用一个超类和它的一个构造函数创建一个类的所有有效方法是什么呢?

  • 我对编程和C++相当陌生。我有一个函数,我想接受以模板化值作为参数的函数指针。我的意思是... 我有这个功能: 我试过的: 结果: .h:165:22:注意:已忽略候选模板:无法将“function ,allocator >&)”与“void(*)(bool,std::vectorstd::vectorstd::allocatorstd::tuple &)”void postgrescaller:

  • 我试图在静态编程语言中创建一个非常简单的泛型NDArray类,它将lambda表达式作为初始化函数。 典型的用法是: 我的问题是Kotlin编译器抱怨构造函数中值的初始化 通过说“不能使用‘T’作为具体化类型参数。改用类”。为什么? 编辑: 如果我用我自己的MyArray替换静态编程语言Array实现,它会编译: 不确定为什么静态编程语言对待MyArray与常规数组不同,当两者具有相同的构造函数时

  • 我有一个kotlin库项目,并使用进行测试。在我的测试中,我尝试使用以下函数: 是正确的行为吗?

  • 我是kotlin的新手,我总是编写java。我尝试了kotlin以java方式编写的一些函数代码,但不起作用。 我将这些代码翻译成java,它就可以工作了。 即使FInter是java接口。它也不起作用。 使现代化 我尝试了一些不同的方法,现在它们都是工作。

  • 当从期望SAM(单抽象方法)类型参数的Java API调用方法时,是否有一致的方法将函数文字强制为正确的类型?我发现,有时Kotlin函数可以很好地工作,而其他函数似乎没有任何一致性。 我有几个来自Ratpack API的示例: 调用ChainAction时。handler(String,handler)使用Kotlin函数文字效果很好,例如: 类型推断发现上下文是一个ratpack。处理。背景