Signup/Sign In

Kotlin Interface

In this tutorial, we will learn about Kotlin Interfaces. Interfaces in Kotlin are similar to abstract classes with some key differences.

An interface can be considered as a fully abstract class. It means by default all functions and properties of an interface are abstract.

An interface is used to define the blueprint of a class, which means we can provide the names of the function along with the complete declaration of the function including its arguments and return type, in an Interface and when any class will implement that Interface then that class will have to provide definition to those functions.

Before Java 8, only function declaration was allowed in interfaces. We could not define the body of functions in interfaces. But in Java 8, we got the functionality to add function body also. Kotlin by default provides this feature. Thus in Kotlin, functions can have a body in interfaces also.

This makes interfaces and abstract classes very similar. The key difference between abstract class and interface is: a class can only inherit one abstract class but it can inherit many interfaces. If there is need to inherit more than one classes then we can opt for interfaces.

Kotlin Interface

The syntax to define an interface in Kotlin is:

interface A{
    var x:Int       // abstract property
    fun sayHello()  // asbtract method
    fun sayBye(){   
        // Default implementation of sayBye()
    }
}

By default, all properties and functions of interfaces are abstract, unless we provide their implementation.

Kotlin: Implementing Interfaces

Interfaces are also inherited using same : operator which is used to inherit a class. Let us create a class C which inherites interfaces A and B:

// first interface
interface A{
    fun sayHelloByA()
    fun sayByeByA(){
        println("Bye from A....")
    }
}
// second interface
interface B{
    fun sayHelloByB()
    fun sayByeByB(){
        println("Bye from B....")
    }
}
// class implementing first and second interface
class C: A,B{
    override fun sayHelloByA() {
        println("Hello from overridden A....")
    }

    override fun sayHelloByB() {
        println("Hello from overridden B....")
    }
}

In this example, both interfaces A and B have two functions: one is abstract and one with default implementation. The class C inherites both the interfaces and overrides their abstract functions.

Let us create object of class C and call its functions:

fun main() {
    val c = C()
    c.sayHelloByA()
    c.sayHelloByB()
    c.sayByeByA()
    c.sayByeByB()
}


Hello from overridden A....
Hello from overridden B....
Bye from A....
Bye from B....

If two interfaces have the same function?

Suppose interface A and interface B both have a function named sayHello() with default implementations. Now if class C inherits both interfaces A and B then there will be a conflict. The class C will give an error:

interface A{
    fun sayHello(){
        println("Hello from A....")
    }
}
interface B{
    fun sayHello(){
        println("Hello from B....")
    }
}
class C: A,B {      // Error
    
}


Error:(11, 1) Kotlin: Class 'C' must override public open fun sayHello(): Unit defined in A because it inherits multiple interface methods of it

It is because class C got implementations of method sayHello() from both interface A and B. In order to resolve this conflict the class C must override sayHello() method and provide its implementation:

interface A{
    fun sayHello(){
        println("Hello from A....")
    }
}
interface B{
    fun sayHello(){
        println("Hello from B....")
    }
}
class C: A,B {
    override fun sayHello() {
        println("Hello from C....")
    }
}

fun main() {
    val c = C()
    c.sayHello()
}


Hello from C....

Calls A's or B's implementation:

Instead of providing our own implementation, if we want to call A's or B's implementation of sayHello() then we can call it using the super keyword and the interface name, like this:

interface A{
    fun sayHello(){
        println("Hello from A....")
    }
}
interface B{
    fun sayHello(){
        println("Hello from B....")
    }
}
class C: A,B {
    override fun sayHello() {
        super<A>.sayHello()
        super<B>.sayHello()
    }
}

fun main() {
    val c = C()
    c.sayHello()
}


Hello from A....
Hello from B....

Summary

In this tutorial, we learned about interfaces and their implementations in Kotlin. We also saw how to resolve conflict if two interfaces have same methods declaration, and we covered the order of function call in case of multple interfaces. In the next tutorial we will discuss about nested and inner classes.



About the author:
I'm a writer at studytonight.com.