Kotlin: Interface … does not have constructors

前端 未结 7 1135
长情又很酷
长情又很酷 2020-12-04 16:14

I am converting some of my Java code to Kotlin and I do not quite understand how to instantiate interfaces that are defined in Kotlin code. As an example, I have an interfac

相关标签:
7条回答
  • 2020-12-04 16:28
    class YourClass : YourInterface {  
        override fun getTest() = "test"    
    }
    
    interface YourInterface {
        fun getTest(): String
    }
    
    val objectYourClass: YourInterface = YourClass()
    print(objectYourClass.getTest())
    
    0 讨论(0)
  • 2020-12-04 16:32

    SAM conversion is supported for interfaces defined in Kotlin since 1.4.0

    What's New in Kotlin 1.4.0

    Before Kotlin 1.4.0, you could apply SAM (Single Abstract Method) conversions only when working with Java methods and Java interfaces from Kotlin. From now on, you can use SAM conversions for Kotlin interfaces as well. To do so, mark a Kotlin interface explicitly as functional with the fun modifier.

    SAM conversion applies if you pass a lambda as an argument when an interface with only one single abstract method is expected as a parameter. In this case, the compiler automatically converts the lambda to an instance of the class that implements the abstract member function.

    So the example in Your question will look something like this:

    fun interface MyInterface
    {
        fun onLocationMeasured(location: String)
    }
    
    fun main()
    {
        val myObj = MyInterface { println(it) }
    
        myObj.onLocationMeasured("New York")
    }
    
    0 讨论(0)
  • 2020-12-04 16:37

    If the interface is for a listener method of a class, change the interface definition to the function type. That makes the code more concise. See the following.

    Class containing listener definition

    // A class
    private var mLocationMeasuredListener = (location: Location) -> Unit = {}
    
    var setOnLocationMeasuredListener(listener: (location: Location) -> Unit) {
        mLocationMeasuredListener = listener
    }
    
    // somewhere in A class
    mLocationMeasuredListener(location)
    

    Another class

    // B class
    aClass.setOnLocationMeasuredListener { location ->
        // your code
    }
    
    0 讨论(0)
  • 2020-12-04 16:41

    The best solution is to use a typealias in-place of your Java interface

    typealias MyInterface = (Location) -> Unit

    fun addLocationHandler(myInterface:MyInterface) {
    
    }
    

    Register it like this:

    val myObject = { location -> ...}
    addLocationHandler(myObject)
    

    or even cleaner

    addLocationHandler { location -> ...}
    

    Invoke it like this:

    myInterface.invoke(location)
    

    The 3 current options seem to be:

    • typealias (messy when called from java)
    • kotlin interface (messy when called from kotlin; you need to create an object) This is a big step back IMO.
    • java interface (less messy when called from kotlin; lambda needs interface name prepended so you don't need an object; also can't use lambda outside of function parenthesis convention)

    When converting our libraries to Kotlin, we actually left all the interfaces in Java code, as it was cleaner to call Java from Kotlin than Kotlin from Kotlin.

    0 讨论(0)
  • 2020-12-04 16:42

    if you have Java class like this :

    recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
            {
                  //Your Code
            }));
    

    you shoud convert this code from Java to Kotlin like this :

    override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
            adapter.addData(list)
            jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
                    activity ,
                    jozlist_recycler ,
                    object : RecyclerTouchListener.ClickListener
                        {
                              //Your Code
                        }))
    

    convert Java Interface :

    new RecyclerTouchListener.ClickListener()
    

    to Kotlin Interface Style:

    object : RecyclerTouchListener.ClickListener
    
    0 讨论(0)
  • 2020-12-04 16:45

    Your Java code relies on SAM conversion - an automatic conversion of a lambda into an interface with a single abstract method. SAM conversion is currently not supported for interfaces defined in Kotlin. Instead, you need to define an anonymous object implementing the interface:

    val obj = object : MyInterface {
        override fun onLocationMeasured(location: Location) { ... }
    }
    
    0 讨论(0)
提交回复
热议问题