我正在开发一个包含一些视图的android库。这些视图自然会发出事件。
我有一个名为的接口(仅出于此问题的目的)Listener。如果我用Java编写该库,则内容将如下所示:
public interface Listener {
void onEvent();
}
Run Code Online (Sandbox Code Playgroud)
public class SomeView extends FrameLayout {
// Some more functions and implementation details
public void setListener(Listener l) { ... }
}
Run Code Online (Sandbox Code Playgroud)
在Kotlin活动中使用此视图时,可以这样使用setListener:
someViewInstance.setListener {
// implementation
}
Run Code Online (Sandbox Code Playgroud)
我想用Kotlin写我的库,但是它也可能用在Java代码中,所以我想像常规视图(如上图)一样为侦听器提供和接口,但是可以选择Kotlin代码使用该函数实施:
interface Listener {
fun onEvent()
}
Run Code Online (Sandbox Code Playgroud)
当我尝试setListener在Kotlin测试活动中像上面那样使用时,出现编译错误,指出该函数需要类型Listener但得到了() -> Unit。
有没有一种方法可以在Kotlin中启用这种实现而不必为此创建新功能?
我考虑过只接收一个函数,() -> Unit但是在Java代码(Function1等等)中看起来很奇怪。
谢谢!
您可以根据建议定义界面,还可以添加扩展名,以允许使用lambda,这对于Kotlin代码而言更为惯用。
class SomeView {
fun setListener(l: Listener) {}
}
fun SomeView.setListener(l: () -> Unit) = setListener(object : Listener {
override fun onEvent() = l()
})
Run Code Online (Sandbox Code Playgroud)
在Java中,您仍然可以通过Listener实现。
这称为SAM转换,
就像Java 8一样,Kotlin支持SAM转换。这意味着只要接口方法的参数类型与Kotlin函数的参数类型匹配,就可以使用单个非默认方法将Kotlin函数文字自动转换为Java接口的实现。
但
请注意,SAM转换仅适用于接口,不适用于抽象类,即使它们也只有一个抽象方法。
另请注意,此功能仅适用于Java互操作。由于Kotlin具有适当的功能类型,因此不需要将功能自动转换为Kotlin接口的实现,因此不受支持。
因此,您无法编写简单的Kotlin代码来模拟此调用。
在Java中,如果您编写一个
public interface Listener {
void onEvent(); // SAM: Single Abstract Method. Only 1 is allowed
}
Run Code Online (Sandbox Code Playgroud)
你有一个
public class SomeView extends FrameLayout {
// skip the constructors
public void setListener(Listener listener) {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
然后,借助SAM转换,您可以在Kotlin中进行这样的花哨呼叫:
SomeView(this).setListener {} // asking a parameter with type () -> Unit for setListener
// Then parenthesis of function call can be omitted
// setListener function can also accept a parameter with type Listener
// by object : Listener {}
Run Code Online (Sandbox Code Playgroud)
但是,如果您将Java文件转换为Kotlin,则由于上述原因,代码将报告错误。例如,您必须自己实现一个SomeView.setListener(() -> Unit)功能
fun SomeView.setListener(l: () -> Unit) {
listener = object : Listener{
override fun onEvent() {
l()
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
846 次 |
| 最近记录: |