我正在将我的一些Java代码转换为Kotlin,我不太了解如何实例化Kotlin代码中定义的接口。作为一个例子,我有一个接口(在Java代码中定义):
public interface MyInterface {
void onLocationMeasured(Location location);
}
然后在我的Kotlin代码中,我实例化了这个界面:
val myObj = new MyInterface { Log.d("...", "...") }
它工作正常。但是,当我将MyInterface转换为Kotlin时:
interface MyInterface {
fun onLocationMeasured(location: Location)
}
当我尝试实例化时,我收到一条错误消息:Interface MyListener does not have constructors
- 虽然在我看来除了语法之外什么都没有改变。我是否误解了Kotlin中接口的工作原理?
答案 0 :(得分:155)
您的Java代码依赖于SAM转换 - 使用单个抽象方法将lambda自动转换为接口。对于Kotlin中定义的接口,SAM转换为currently not supported。相反,您需要定义实现接口的匿名对象:
val obj = object : MyInterface {
override fun onLocationMeasured(location: Location) { ... }
}
答案 1 :(得分:14)
最佳解决方案是使用Java接口的类型
typealias MyInterface = (Location) -> Unit
fun addLocationHandler(myInterface:MyInterface) {
}
像这样注册:
val myObject = { location -> ...}
addLocationHandler(myObject)
甚至更清洁
addLocationHandler { location -> ...}
像这样调用它:
myInterface.invoke(location)
目前的3个选项似乎是:
在将我们的库转换为Kotlin时,我们实际上将所有接口都保留在Java代码中,因为从Kotlin调用Java比从Kotlin调用Kotlin更简洁。
答案 2 :(得分:5)
如果您有 Java class ,请执行以下操作:
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
{
//Your Code
}));
您应该将此代码从Java转换为 Kotlin ,如下所示:
override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
adapter.addData(list)
jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
activity ,
jozlist_recycler ,
object : RecyclerTouchListener.ClickListener
{
//Your Code
}))
转换 Java接口:
new RecyclerTouchListener.ClickListener()
到 Kotlin界面样式:
object : RecyclerTouchListener.ClickListener
答案 3 :(得分:4)
1.4.0
起, 在Kotlin中定义的接口支持SAM转换。
在Kotlin SAM转换。在这种情况下,编译器会自动将lambda转换为实现抽象成员函数的类的实例。 所以您的问题中的示例将如下所示:
1.4.0
之前,仅当使用Kotlin的Java方法和Java接口时,才能应用SAM(单一抽象方法)转换。从现在开始,您还可以将SAM转换用于Kotlin接口。为此,请使用 fun
修饰符将Kotlin界面明确标记为可以正常工作。
如果仅将一个抽象方法的接口作为参数,则在传递lambda作为参数时,将应用
fun interface MyInterface
{
fun onLocationMeasured(location: String)
}
fun main()
{
val myObj = MyInterface { println(it) }
myObj.onLocationMeasured("New York")
}
答案 4 :(得分:3)
尝试像这样访问您的界面:
object : MyInterface {
override fun onSomething() { ... }
}
答案 5 :(得分:0)
如果接口用于类的侦听器方法,则将接口定义更改为函数类型。这使代码更加简洁。请参阅以下内容。
包含侦听器定义的类
// A class
private var mLocationMeasuredListener = (location: Location) -> Unit = {}
var setOnLocationMeasuredListener(listener: (location: Location) -> Unit) {
mLocationMeasuredListener = listener
}
// somewhere in A class
mLocationMeasuredListener(location)
另一堂课
// B class
aClass.setOnLocationMeasuredListener { location ->
// your code
}
答案 6 :(得分:0)
class YourClass : YourInterface {
override fun getTest() = "test"
}
interface YourInterface {
fun getTest(): String
}
val objectYourClass: YourInterface = YourClass()
print(objectYourClass.getTest())