Kotlin Interfaces(With Examples)

This article is about interfaces and how to implement it in Kotlin with the help of simple examples.

Interfaces

In Kotlin, Interfaces can contain declarations of abstract methods (have no body), as well as method implementation of non-abstract methods. 

Interfaces can have properties but these need to be abstract or to provide accessor implementations.

Creating Interface

To declare an interface, we use interface keyword.

//By default interfaces and 
//abstract members(properties and methods) 
//are public abstract
public abstract interface MusicPlayer {
    public abstract var defaultVolume: String   // abstract property

    public abstract fun play()          // abstract function
    fun stop() = "the MusicPlayer is in stop mode" // function with default implementation
}

Here, MusicPlayer is an interface which contains a property defaultVolume , abstract function play() and non-abstract function stop() .

Note: Interfaces and Interface members (abstract and non-abstract) are always open. You do not need to explicitly use open keyword.

Implementing an Interface

Interfaces cannot be instantiated because it contains abstract members (have no implementation). But, we can implement interfaces in other classes.

The class which implements Interface must override all abstract members (abstract properties and abstract methods) of Interface or you have to declare class as abstract class.

Example
//Implementing an interface example
interface MusicPlayer {

    fun play()  //abstract function

    fun stop()  //abstract function

    //non-abstract function with default implementation
    fun setVolume(x: Int) {

        System.out.println("Player volume Changed by: " + x);
    }

}

//MP3Player class implementing MusicPlayer interface.
//It must override all the abstract functions of MusicPlayer interface.
class MP3Player : MusicPlayer {

    //implementation of play abstract function
    override fun play() {
        println("the MP3 Player is playing.")
    }

    //implementation of stop abstract function
    override fun stop() {
        println("the MP3 Player is off.")
    }

    //implementation of setVolume function 
    override fun setVolume(x: Int) {

        if (x <= 100) {
            System.out.println("Player volume Changed by: " + x);
        } else {
            System.out.println("Player volume level should be less than 100.");
        }
    }
}

fun main() {
    val mP3Player = MP3Player()
    mP3Player.play()
    //setVolume function of MP3Player class get executed
    mP3Player.setVolume(110)
}
Output
the MP3 Player is playing.
Player volume level should be less than 100.
Example explained
  • MusicPlayer is an interface which contains a non-abstract function setVolume() and two abstract functions play() and stop().
  • The class MP3Player implements interface MusicPlayer and overrides its functions (abstract and non-abstract functions).
  • mP3Player is an object of MP3Player class. The statement mP3Player.play() will execute the play function and mP3Player.setVolume() will execute the setVolume function of MP3Player class.

Note: If a class implementing the Interface does not override a non-abstract function of Interface, then the compiler will execute the default implementation of that function within the Interface.

Properties in Interfaces

You can declare properties in interfaces. A property declared in an interface can either be abstract, or it can provide implementations for accessors.

Properties declared in interfaces can’t have backing fields, and therefore accessors declared in interfaces can’t reference them.

Example
//interface
interface Addition {

    val numOne: Int // abstract property

    val numTwo: Int  //property with implementation
        get() = 6

    //function with default implementation
    fun add() {
        println("Sum of $numOne and $numTwo is: " + (numOne + numTwo))
    }

}

class Number : Addition {

    override val numOne = 5

    override fun add() {
        //add function of Addition Interface get executed
        super.add()
    }
}

fun main() {
    val number = Number()
    //add function of Number class get executed
    number.add()
}
Output
Sum of 5 and 6 is: 11

Interface reference type

We cannot create an object of any interface but Interfaces can be used as reference type for the object of an implementing class.

Using interface reference type we can only access its own functions and properties.

Example
//Interface 
interface MusicPlayer {

    fun play()  //abstract function

    fun stop()  //abstract function

}

//MP3Player class implementing MusicPlayer interface.
class MP3Player : MusicPlayer {

    //implementation of play abstract function
    override fun play() {
        println("the MP3 Player is playing.")
    }

    //implementation of stop abstract function
    override fun stop() {
        println("the MP3 Player is in stop mode.")
    }

    //MP3Player class non-abstract function
    fun pause() {
        println("the MP3 Player is in pause mode.")
    }
}

fun main() {
   //Using interface reference type 
    val mP3Player: MusicPlayer = MP3Player()
    mP3Player.play()
    mP3Player.stop()
    //using interface reference type we can only access its own members.
    //mP3Player.pause() //error: interface MusicPlayer does not contain any pause function
}
Output
the MP3 Player is playing.
the MP3 Player is in stop mode.

Multiple inheritance by interface

Kotlin does not support multiple inheritance which means that a class cannot extend more than one class.

But, multiple inheritance using interfaces is possible. We can implement multiple Interfaces in a single class.

A class implementing Interfaces must implement all the abstract methods of all the Interfaces.

Example
//Interface
interface MusicPlayer {

    fun play()  //abstract function

    fun stop()  //abstract function
}

//Interface
interface VideoPlayer {

    fun changeBrightness(x: Int)  //abstract function

    fun changeContrast(x: Int)  //abstract function
}

//SmartPhone class implementing interfaces MusicPlayer,VideoPlayer
class SmartPhone : MusicPlayer, VideoPlayer {

    //implementation of play abstract function
    override fun play() {
        println("Player is playing.")
    }

    //implementation of stop abstract function
    override fun stop() {
        println("Player stopped.")
    }

    //implementation of changeBrightness abstract function
    override fun changeBrightness(x: Int) {
        println("Brightness Changed by: " + x)
    }

    //implementation of changeContrast abstract function
    override fun changeContrast(x: Int) {
        println("Contrast Changed by: " + x)
    }
}

fun main() {
    val smartPhone = SmartPhone()
    smartPhone.play()
    smartPhone.changeBrightness(30)
}
Output
Player is playing.
Brightness Changed by: 30

Resolving overriding conflicts (multiple Interfaces having same method)

In case both the implemented interfaces contain non-abstract method (let’s say next() method) with same method signature, the implementing class must override the next() method and this method must explicitly specify which next() method is to be used.

Example
//Interface
interface MusicPlayer {

    //fun play()

    //fun stop()

//next function of MusicPlayer Interface
//with default implementation
    fun next() {
        println("Next from MusicPlayer")
    }
}

//Interface
interface VideoPlayer {

    //fun changeBrightness(x: Int)

    //fun changeContrast(x: Int)

//next function of VideoPlayer Interface
//with default implementation
    fun next() {
        println("Next from VideoPlayer")
    }
}

//SmartPhone class implementing interfaces MusicPlayer,VideoPlayer
class SmartPhone : VideoPlayer, MusicPlayer {

    //overriding next() function
    override fun next() {

        //use super keyword to call the next
        //function of MusicPlayer interface
        super<MusicPlayer>.next()

        //use super keyword to call the next
        //function of VideoPlayer interface
        super<VideoPlayer>.next()
    }
}

fun main() {
    val smartPhone = SmartPhone()
    //next function of SmartPhone class get executed
    smartPhone.next()
}
Output
Next from MusicPlayer
Next from VideoPlayer

Inheriting an Interface

An interface can inherit another interface or interfaces (more than one interface) .

Any class that implements an interface must implement the abstract members declared in that interface plus all the abstract members that are present in the super interface.

If the implementing class is abstract it may choose to implement all, some or none of the methods declared in the interface.

Example
//Interfaces inheritance example
interface Player {

    fun play()  //abstract function

    fun stop()  //abstract function
}

//VideoPlayer interface inheriting Player interface
interface VideoPlayer : Player {

    fun changeBrightness(x: Int)  //abstract function

    //function with default implementation
    fun next() {
        System.out.println("Next from VideoPlayer")
    }
}

//SmartPhone class implementing VideoPlayer interface
class SmartPhone : VideoPlayer {

    //implementation of play abstract function
    override fun play() {
        println("video playing..")
    }

    //implementation of stop abstract function
    override fun stop() {
        println("video stopped..")
    }

    //implementation of changeBrightness abstract function
    override fun changeBrightness(x: Int) {
        println("Brightness Changed by: " + x)
    }
}

fun main() {
    val smartPhone = SmartPhone()
    smartPhone.play()
    smartPhone.changeBrightness(30)
    smartPhone.next()
}
Output
video playing..
Brightness Changed by: 30
Next from VideoPlayer

Points to Remember:

  • Interfaces can contain declarations of abstract methods (have no body), as well as method implementations. 
  • Interface also contains properties which can either be abstract, or it can provide implementations for accessors.
  • Interfaces cannot be instantiated. They can only be implemented by an implementing class or extended by another interface.
  • Interfaces can be used as reference type for the object of an implementing class.
  • A class that implements interface must provide implementation to all the abstract methods of interface or you have to declare it as abstract class.
  • A class can implement more than one interface.
  • An interface can inherit more than one interface.
  • Kotlin does not support multiple inheritance using class, but by using interface it can achieve multiple inheritance.
  • Interface is used to achieve abstraction and loose coupling.

Leave a Reply