如何在Kotlin中指定ActionListener?
我想向Kotlin中的JButton添加ActionListener。在Java中,我只需编写以下内容:如何在Kotlin中指定ActionListener?,kotlin,Kotlin,我想向Kotlin中的JButton添加ActionListener。在Java中,我只需编写以下内容: JPanel makeButtonPanel() { JPanel panel = new JPanel(new FlowLayout()); JButton dirButton = new JButton("Change directory"); dirButton.addActionListener(e -> chooseDirectory());
JPanel makeButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton dirButton = new JButton("Change directory");
dirButton.addActionListener(e -> chooseDirectory());
panel.add(dirButton)
return panel;
}
但在科特林,事情并不是那么简单。我第一次尝试这个:
private fun makeButtonPanel() : JPanel {
val panel = JPanel(FlowLayout())
val dirButton = JButton("Choose")
dirButton.addActionListener(e -> chooseDirectory()) // error message here
// ...
}
private fun chooseDirectory() { ... }
但我收到了这个错误信息:
Type Mismatch
Required: ((ActionEvent!) -> Unit)!
Found: KFunction1<ActionEvent, Unit>
类型不匹配
必需:((ActionEvent!)->单元)!
找到:KFunction1
我明白了!这意味着这是一个具有不确定可空性的java方法,但这并不能帮助我理解如何编写它。我只想让它调用chooseddirectory()方法。一定有一个干净、简单的方法可以做到这一点,但我看不到。好吧,我想出来了,而且非常简单。我只要省去括号,说
dirButton.addActionListener { chooseDirectory() }
我仍然不清楚什么时候应该用大括号而不是圆括号。正如您所发现的,您需要使用大括号(
{
}
)
这是因为大括号是在Kotlin中定义lambda的必要部分。 (这与Java和Scala等语言不同,后者的必要部分是->
或=>
箭头。 这是因为在Kotlin中,如果有一个或没有参数,则箭头是可选的;如果有,则使用关键字。)
如果没有大括号,代码将调用chooseddirectory()
函数,并尝试将其结果传递给addActionListener()
——这显然是行不通的
大括号也足够了:它们被视为定义lambda,除非您给出了函数或方法的主体,或者在分支时给出了if
/。 (同样,这与大多数类似C/Java的语言不同。 在Kotlin中,如果只需要块作用域,则必须使用以下构造。)
至于括号,它们在这里是可选的。 如果需要,您可以将其包括在内:
dirButton.addActionListener({ chooseDirectory() })
但是Kotlin有一个如果一个函数的最后一个参数是一个函数,你可以在参数之后传递它:
dirButton.addActionListener(){ chooseDirectory() }
如果这会使paren为空,那么您可以完全忽略它们:
dirButton.addActionListener{ chooseDirectory() }
这是为了让函数看起来像新的语言语法。 例如,您可能满足以下功能:
with(someObject) {
itsProperty = someValue
}
这只是一个非常普通的函数,在标准库中定义,并将函数作为其最后一个参数。 同样地:
还有一件事值得一提。 在Kotlin中,lambda是定义的一种方式,它是一类类型,可以像其他类型一样定义、传递和使用。 这与Java不同,Java传统上使用接口来实现这些目的——通常是使用单一抽象方法(“SAM接口”)的接口——在Java中,lambda只不过是定义此类接口匿名实现的语法糖
作为一种特殊情况,为了实现互操作性,Kotlin使用lambda来定义Java SAM接口(或者,自Kotlin 1.4以来,定义Kotlin)的实现,而不是函数
ActionListener
是一个Java SAM接口,这就是为什么您可以在这里使用lambda。在kotlinI中使用大括号({}
)而不是普通括号(()
)来表示lambda表达式。我将尝试在回答中解释这些问题。 (注释太多了!)大括号用于使用lambda语法定义它。您也可以执行dirButton.addActionListener(::chooseddirectory)
来使用函数引用语法。还有其他方法可以指定它,比如使用匿名对象语法或命名函数语法。如果您只是调用另一个函数,那么函数引用语法通常更可取。否则,lambda通常会生成最干净的代码。
repeat(10) {
// Some code to be run 10 times…
}