Kotlin - Read Only properties in interfaces

6.3k views Asked by At

I have this utility interface to be implemented by RecyclerView's ViewHolder that fires UI events.

interface ObservableMvpViewHolder<V> {
    val listeners: List<V>

    fun registerListener(listener:V)
    fun unregisterListener (listener: V)

}

the listeners property is like a contract so I want to obligate the clients to declare it to store the observers.

but when I implement this interface I have to declare a getter to this property:

class AddItemViewHolderHolder(override val containerView: View) : ViewHolder(containerView), LayoutContainer, ObservableMvpViewHolder<AddItemViewHolderHolder.Listener> {
        override val listeners: List<Listener>
            get() = listeners

I don't want to do that to avoid to expose this property to the outside.

I'm new to Kotlin, is there a way to do that without having to declare an abstract class?

3

There are 3 answers

1
sound On

Interface as you've said are Contract that you let everyone read, therefore, it doesn't make sense to hide a property that is part of that contract.

They (The Interfaces)can have properties but these need to be abstract or to provide accessor implementations.

Interface Documentation

So as you've said, you could achieve this behavior using an abstract class :

abstract class ObservableMvpViewHolder<V> {
    private val listeners : List<V> = emptyList()

    abstract fun registerListener(listener:V)
    abstract fun unregisterListener (listener: V)

}
0
Sergio On

In Kotlin all properties in an interface are abstract, they can't be initialized. But you can have custom getters and setters, e.g:

interface ObservableMvpViewHolder<V> {
    val listeners: List<V>
        get() = listOf()

    fun registerListener(listener:V)
    fun unregisterListener (listener: V)
}
1
P.J.Meisch On

Why do you add the property to the interface at all? The contract you want to define is the ability to add and remove listeners and probably to get the list of all actual listeners. So the interface would be like this:

interface ObservableMvpViewHolder<V> {
  fun registerListener(listener:V)
  fun unregisterListener (listener: V)
  fun listeners(): List<V>
}

If an implementation of this interface uses an ArrayList, a LinkedList or whatever to store the listeners is an implementation detail which should not be in the interface.