Kotlin Interface Examples

Interface define contract for classes. An interface is similar to a class just that, it's a collection of abstract methods and variables. Essentially Interfaces are one level more abstract than abstract classes.

Let's say we have an interface called Driveable.
interface Driveable {
  fun drive() // declaring 'abstract' is implicit and unnecessary
}
we can then have different vehicles (e.g Car, Truck, Lorry, Motorcycle, Ship, Plane etc) implement the interface and override the drive method.

now let's see how we implement it
interface Driveable  {
    fun drive()
    fun refuel()
}
class Car(var color : String) : Driveable{
    override fun drive() {
        println("Driving my $color car...")
    }
    override fun refuel() {
        println("Re-Fueling my car ...")
    }
}
class Truck (var color: String) : Driveable{
    override fun drive() {
        println("Driving my $color Truck...")
    }
    override fun refuel() {
        println("Re-Fueling my Truck...")
    }
}
need to implement multiple interfaces? introduce a comma!
interface Driveable  {
    fun drive()
    fun refuel()
}
interface Buildable {
    fun build()
}
class Car(var color : String) : Driveable, Buildable{ 
    override fun build() {
        println("Built a Shiny Car!")
    }
    override fun drive() {
        println("Driving my $color car...")
    }
    override fun refuel() {
        println("Re-Fueling my car...")
    }
}

class Truck (var color: String) : Driveable, Buildable
    override fun build() {
        println("Built a Shiny Truck!")
    }
    override fun drive() {
        println("Driving $color Truck...")
    }
    override fun refuel() {
        println("Re-Fueling my Truck...")
    }
}
Interfaces can also hold variables
interface Driveable  {
    fun drive()
    fun refuel()
}
interface Buildable {
    var timeRequiredToBuild : Int //cannot have any specific value (or state) e.g timeRequiredToBuild = 10
    fun build()
}
class Car(var color : String) : Driveable, Buildable{
    override var timeRequiredToBuild: Int = 120 // overrode the variable
    override fun build() {
        println("Built a Shiny Car!")
    }
    override fun drive() {
        println("Driving my $color car...")
    }
    override fun refuel() {
        println("Re-Fueling my car...")
    }
}
Functions for interfaces can have default implementation. This feature was added to Java language (available in Java 8 or higher).
interface Driveable {
    fun drive(){
        println("DRIVING SOMETHING!") // default implementation
    }
}
Interfaces and polymorphism

[box type="info" align="" class="" width=""]Poly = many, morph- = change or form

So polymorphism is the ability (in programming) to present the same interface for differing underlying forms (data types).

Polymorphism is when you can treat an object as a generic version of something, but when you access it, the code determines which exact type it is and calls the associated code.
[/box]
interface Driveable {
    fun drive()
}

interface Buildable {
    var timeRequiredToBuild: Int //cannot have any specific value (or state) e.g timeRequiredToBuild = 10
    fun build()
}

class Car(var color: String) : Driveable, Buildable {
    override var timeRequiredToBuild: Int = 120

    override fun build() {
        println("Built a Shiny Car!")
    }

    override fun drive() {
        println("Driving my $color car...")
    }
}

class Truck(var color: String) : Driveable, Buildable {
    override var timeRequiredToBuild: Int = 300
    override fun build() {
        println("Built a Shiny Truck!")
    }

    override fun drive() {
        println("Driving $color Truck...")
    }
}

class InterfaceExample {
    fun main(args: Array<String>) {
        val car: Driveable = Car("Red")
        // we can cast car to Driveable because
        // our interface implements Driveable
        // doing that only allow us to only use
        // methods within Driveable interface

        car.drive() //this will compile
        car.build() // will NOT compile becase we  -
        // already speficied we only want to work with
        // methods inside driveable
        val truck: Driveable = Truck("Black")
        // casting to the interface Driveable allows to
        truck.drive()
    }
}
Why should you use val car: Driveable = Car("Red") instead of val car: Car = Car("Red") ??

The main reason you'd do this is to decouple your code from a specific implementation of the interface. When you write your code like this: val car: Car = Car("Red") the rest of your code only knows that data is of type Driveable , which is preferable because it allows you to switch between different implementations of the Driveable Interface with ease.

For instance, say you were writing a fairly large 3rd party library, and say that you decided to implement the core of your library with a Truck. If your library relies heavily on accessing elements in the Driveable Interface, then eventually you'll find that you've made a poor design decision. Assuming you have been programming to an interface, making such a change is easy. You would simply change the instance of car from, val car : Driveable = Car()to val car : Driveable = Truck()and you know that this will work because you have written your code to follow the contract provided by the Driveable interface.

On the other hand, if you had implemented the core of your library using val car : Car = Car(), making such a change wouldn't be as easy, as there is no guarantee that the rest of your code doesn't make use of methods specific to the Car class.

All in all, the choice is simply a matter of design... but this kind of design is very important (especially when working on large projects), as it will allow you to make implementation-specific changes later without breaking existing code.

Comments

Popular posts from this blog

How to select Multiple Item in RecyclerView in Android

Android Clipboard Listener - How to Know when User copies a text in Android

Kotlin ArrayList and Loops Example