Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing interface instance variables

I would like to inject (enrich) behavior and state in a Kotlin class by using an interface. Like class Impl : Observable, where Observable contains state.

In Scala using Traits (does work), looking for a Kotlin solution for this one:

object Test extends App {
  val impl = new Impl()
  val observer = new Observer()
  impl.register(observer)
}

trait Observable {
  // How to do this in Kotlin?
  val observers = List()

  def register(observer: Observer) {
    observers.add(observer)
  }
}
class Observer

class Parent
class Impl extends Parent with Observable

Attempt in Kotlin (not working):

fun main(args: Array<String>) {
    val impl = Impl()
    val observer = Observer()
    impl.register(observer)
}

interface Observable {
    // Error: Kotlin: Property initializers are not allowed in interfaces
    val observers = mutableListOf<Observer>()

    fun register(observer: Observer) {
        observers.add(observer)
    }
}
class Observer

open class Parent
class Impl : Parent(), Observable

It results in this error at the interface instance variable line: Kotlin: Property initializers are not allowed in interfaces. How can I initialize instance variables in Kotlin interfaces? (Note that in this design, parent classes shouldn't be altered/updated.)

UPDATE: I had an example solution in Java, but that wasn't behaving correctly. "Instance variables" in Java interfaces are automatically static. So I have removed that example.

like image 888
Devabc Avatar asked Dec 23 '22 09:12

Devabc


1 Answers

You can have a placeholder for state in Kotlin interfaces, and let the implementing class provide that state. So the interface can provide the functionality that works against the expected-to-exist state. Such as:

class Observer

interface Observable {
    val observers: MutableList<Observer> // not present, but expected

    fun register(observer: Observer) {
        observers.add(observer)
    }
}

open class Parent

class Impl : Parent(), Observable {
    override val observers = mutableListOf<Observer>() // used by the interface
}

This is for good reason, there are delicate issues having state coming from more than one item in the class hierarchy and Kotlin is preventing the problems that can arise from such models.

like image 83
Jayson Minard Avatar answered Dec 28 '22 06:12

Jayson Minard