Kotlin:Interface ...没有构造函数

时间:2017-05-02 12:21:48

标签: java kotlin

我正在将我的一些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中接口的工作原理?

7 个答案:

答案 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个选项似乎是:

  • typealias(从java调用时很乱)
  • kotlin接口(从kotlin调用时很乱;你需要创建一个对象)这是IMO的一大步。
  • java接口(从kotlin调用时不太乱; lambda需要前置接口名称,因此你不需要一个对象;也不能在函数括号约定之外使用lambda)

在将我们的库转换为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转换。

What's New in Kotlin 1.4.0

在Kotlin 1.4.0之前,仅当使用Kotlin的Java方法和Java接口时,才能应用SAM(单一抽象方法)转换。从现在开始,您还可以将SAM转换用于Kotlin接口。为此,请使用 fun 修饰符将Kotlin界面明确标记为可以正常工作。

如果仅将一个抽象方法的接口作为参数,则在传递lambda作为参数时,将应用

SAM转换。在这种情况下,编译器会自动将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())