Interfaces in Kotlin
While working with Java, we had interfaces that would only have static variables or methods without the body. In Kotlin, however, now we can have interfaces with functions that contain a body.
Now, that being said, In this blog, we are going to learn how to define interfaces, use them, and what are the amazing things we can do with interfaces in Kotlin.
But first, let's see what are interfaces (in Java)?
An
interface
is like a abstract class that is used to group related methods with empty bodies. They only have methods inside it which is the implemented by a class to inherit all its methods.
An interface in java can have n-numbers of methods which are abstract and a class can implement any number of interfaces.
In this blog, we will learn,
- How to declare and use interface in Kotlin?
- Interfaces with properties and default implementation.
- Properties in interface
- Inheritance in interface
- Implementing multiple interfaces.
How to declare and use interface in Kotlin?
In Kotlin we declare interfaces like,
interface ResponseListener {
fun onSuccess(response: Response)
fun onError(error: Error)
}
Here, we have an interface that has two abstract functions where Response and Error are data classes like,
data class Response(val data: String)
data class Error(val error: String)
Now, to use this interface, we need to implement it in class like,
class MyView() : ResponseListener {
override fun onSuccess(response: Response) {
}
override fun onError(error: Error) {
}
}
Here, we have created a class MyView that implements our interface and its functions are overridden in the class.
Interfaces with properties and default implementation
We can have a certain
implementation
to the functions in am interface itself and if we don't override them, the implementation works as default value.
Let's say we edit out interface like,
interface ResponseListener {
fun onSuccess(response: Response) {
Log.d("ResponseListener", "onSuccess")
}
fun onError(error: Error) {
Log.d("ResponseListener", "onError")
}
}
And if we implement it now to a class,
class MyView() : ResponseListener {
override fun onSuccess(response: Response) {
super.onSuccess(response)
}
override fun onError(error: Error) {
super.onError(error)
}
}
and initialize the class,
MyView().onError(Error(""))
It will print the following from
onError()
method with its default implementation,
ResponseListener: onError
Properties in interfaces
Similarly, how we have functions in interfaces we can also have different properties in it as well.
Properties can't have their own value as an interface can't have a state.
To set a value to a property we need to first implement it and then override value to it. Let us see this by example.
Consider an interface,
interface SetupAddition {
val numOne: Int
val numTwo: Int
fun add() = numOne + numTwo
}
Here, we have two property
numOne
and
numTwo
. It also has a function
add()
which will return the sum of both numbers. Now, to use this we will implement it in a class like,
class Addition : SetupAddition {
override val numOne: Int
get() = 5
override val numTwo: Int
get() = 10
override fun add(): Int {
return super.add()
}
}
and to get the addition, we create the object of the class like,
Addition().add()
This will print the sum 15.
Here, we first provided two values to the integers and then we called the
add()
function to return the addition.
Inheritance in Interface
We can inherit the property and function from one interface to another.
To understand it better, let's consider we have an interface,
interface Numbers {
var numTwo: Int
fun numOne(): Int // This is a function now
}
Here, we have one property and other is a function, and this
Numbers
interface is implemented by another interface like,
interface SetupAddition : Numbers {
fun add() = numOne() + numTwo
}
Here, you can see in
SetupAddition
we can access both the function and property of
Numbers
interface and can perform the addition it the function of
SetupAddition
interface.
Now, we can use the above interface by,
class Addition() : SetupAddition {
override fun numOne(): Int = 5
override var numTwo: Int = 10
override fun add(): Int {
return super.add()
}
}
Here, you can see that we have implemented the SetupAddition and it overrides the property of Numbers interface as well.
Implementing multiple interfaces
In Kotlin, we can implement multiple interfaces in a class and it will override functions from all interfaces implemented. For example,
Consider we have three interfaces like,
interface Numbers {
var numTwo: Int
fun numOne(): Int //This is a function
}
interface SetupAddition : Numbers {
fun add() = numOne() + numTwo
}
interface ResponseListener {
fun onSuccess(response: Response) {
Log.d("ResponseListener", "onSuccess")
}
fun onError(error: Error) {
Log.d("ResponseListener", "onError")
}
}
Here, SetupAddition is inheriting Numbers and we have another interface called
ResponseListener
. Now, we implement it like,
class MyClass() : SetupAddition,ResponseListener {
override fun numOne(): Int = 5
override var numTwo: Int = 10
override fun add(): Int {
return super.add()
}
override fun onError(error: Error) {
super.onError(error)
}
override fun onSuccess(response: Response) {
super.onSuccess(response)
}
}
In the above class, you can see that we have
implemented
SetupAddition
and
ResponseListener
both interfaces to it.
Now, if we call the error method like,
MyClass().onError(Error(""))
Here it will print the output,
ResponseListener: onError
This is how we can implement and work with interfaces in Kotlin.