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.