Companion Objects in Kotlin Interfaces

mickstar picture mickstar · Feb 10, 2016 · Viewed 17.6k times · Source

I am trying to make a interface Parcelable, as such I need a interface like this

interface AB : Parcelable {
    companion object {
        val CREATOR : Parcelable.Creator<AB>
    }
}

and my two classes A and B looking like

data class A (...): Parcelable{
    ...
    companion object {
        val CREATOR : Parcelable.Creator<AB> = object : Parcelable.Creator<AB> {
            override fun newArray(size: Int): Array<AB?> {
                return arrayOfNulls(size)
            }

            override fun createFromParcel(parcel: Parcel): AB {
                return A(parcel)
            }

        }
    }

I am struggling to implement such a interface in kotlin. It seems the interface class does not allow for the CREATOR

Perhaps I am taking the wrong approach,
I have a parcelable that contains a list of classes that are either A or B so I am doing

parcel.readTypedList(this.list, AB.CREATOR)

I require that the list be either A or B and that is why I am using an interface.

Anyone have any advice or a possible solution?

Answer

Jayson Minard picture Jayson Minard · Feb 11, 2016

In Kotlin, an interface can have a companion object but it is not part of the contract that must be implemented by classes that implement the interface. It is just an object associated to the interface that has one singleton instance. So it is a place you can store things, but doesn't mean anything to the implementation class.

You can however, have an interface that is implemented by a companion object of a class. Maybe you want something more like this:

interface Behavior {
   fun makeName(): String
}

data class MyData(val data: String) {
    companion object: Behavior {  // interface used here
        override fun makeName(): String = "Fred"
    }
}

Note that the data class does not implement the interface, but its companion object does.

A companion object on an interface would be useful for storing constants or helper functions related to the interface, such as:

interface Redirector {
    fun redirectView(newView: String, redirectCode: Int)

    companion object {
        val REDIRECT_WITH_FOCUS = 5
        val REDIRECT_SILENT = 1
    }
}

// which then can be accessed as:
val code = Redirector.REDIRECT_WITH_FOCUS