Interfaces

The interface keyword defines a new interface. Within the interface body you list methods that class must implement. An empty interface is allowed.

Kotlin supports methods with default implementation. Such methods are called non-abstract and can be private.

The override keyword allows you to override a method in an inherited interface or in a class that implements the interface.

An overridden method can change the return type to any subclass.

A class can implement multiple interfaces. A non-abstract class must implement all methods of the specified interfaces.

// an empty interface
interface Empty 

interface InterfaceName {
    fun foo()
    fun bar(arg: Int=56): Boolean
    fun printBar(arg: Int){println("bar is ${bar(arg)}")}
    fun newObj(): ClsA
}

interface InterfaceName2: InterfaceName, Empty {
   override fun newObj(): SubClsA
}

class Cls : InterfaceName, Empty{
    override fun foo(){ ... }
    override fun bar(arg: Int) = arg%2 == 0
    // this class uses default implementation of printBar
}

anonymous instance

An anonymous instance of an interface can be created through an anonymous object.

interface Task {
    fun onTask(workerActions: WorkerActions)
}

var mainTask = object : Task{
            override fun onTask( workerActions: workerActions) {
                TODO("Not yet implemented")
            }
        }

functional interface

You can declare a single abstract method (SAM) interface as a functional interface. This allows you to convert the interface to a lambda function and vice versa.

fun interface Task {
    fun onTask(workerActions: WorkerActions)
}

class Worker{
...

// methods accept interface
open fun onPreProcess(task: Task): Worker{...}
open fun onPostProcess(task: Task): Worker{...}
open fun onMainTask(task: Task): Worker{...}
}

// but we can use lambdas, instead anonymous implementation
val worker = Worker().onMainTask{ actions-> 
        ...
   }.onPreProcess{ actions->
        ...
   }.onPostProcess{ actions->
        ...
   }

properties

You can add properties to the interface. This will be considered a shorthand for getter/setter methods. These properties cannot be initialized.

interface ProgressDataInfo {
    val current: Long
    val total: Long
}

class ProgressData : ProgressDataInfo {
    var mCurrent: Long = 0
    var mTotal: Long = 0

    override val current: Long
        get() = mCurrent

    override val total: Long
        get() = mTotal
}

delegation

A class can delegate the implementation of an interface to another object.

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main() {
    val b = BaseImpl(10)
    Derived(b).print()
}

resolving overriding conflicts

When we declare many types in our supertype list, it may appear that we inherit more than one implementation of the same method.

interface A {
    fun foo() { print("A") }
    fun bar()
}

interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}

class D : A, B {
    override fun foo() {
        super<A>.foo() // call A implementation
        super<B>.foo() // call B implementation
    }

    override fun bar() {
        super<B>.bar() // call B implementation
    }
}