Kotlin Interfaces

An interface defines a contract — a set of functions and properties that implementing classes must provide. Unlike abstract classes, interfaces cannot hold state (no stored properties). A class can implement multiple interfaces, which allows much more flexible design than single-class inheritance.

Defining and Implementing an Interface

interface Printable {
    fun print()
    fun preview(): String
}

class Invoice(val number: Int, val amount: Double) : Printable {
    override fun print() {
        println("Printing Invoice #$number — ₹$amount")
    }

    override fun preview(): String = "Invoice #$number"
}

fun main() {
    val inv = Invoice(1042, 5500.0)
    println(inv.preview())   // Invoice #1042
    inv.print()              // Printing Invoice #1042 — ₹5500.0
}

Interfaces with Default Implementations

Interfaces in Kotlin can provide a default body for functions. Implementing classes can use the default or override it:

interface Greeter {
    val greeting: String
        get() = "Hello"    // default property (computed)

    fun greet(name: String) {
        println("$greeting, $name!")
    }

    fun farewell(name: String) = println("Goodbye, $name!")
}

class FormalGreeter : Greeter {
    override val greeting = "Good day"  // override the greeting
}

class CasualGreeter : Greeter            // use all defaults

fun main() {
    FormalGreeter().greet("Sir Alex")    // Good day, Sir Alex!
    CasualGreeter().greet("Bob")         // Hello, Bob!
    CasualGreeter().farewell("Bob")      // Goodbye, Bob!
}

Multiple Interface Implementation

interface Flyable {
    fun fly() = println("Flying!")
}

interface Swimmable {
    fun swim() = println("Swimming!")
}

interface Runnable {
    fun run() = println("Running!")
}

class Duck : Flyable, Swimmable, Runnable {
    override fun fly()  = println("Duck flaps wings and flies")
    override fun swim() = println("Duck paddles through water")
    // run() uses default: "Running!"
}

fun main() {
    val duck = Duck()
    duck.fly()    // Duck flaps wings and flies
    duck.swim()   // Duck paddles through water
    duck.run()    // Running!
}

Interface vs Abstract Class


             Interface              Abstract Class
─────────────────────────────────────────────────────
Constructor?   NO                   YES
State (stored  NO (only computed    YES
 properties)?  properties)
Implement      multiple            only one
 multiple?
Use when?      defining capability defining a base type

Interface Properties

interface Vehicle {
    val maxSpeed: Int        // abstract — no body
    val fuelType: String     // abstract
    val isElectric: Boolean
        get() = fuelType == "Electric"  // computed with default
}

class Motorcycle(override val maxSpeed: Int) : Vehicle {
    override val fuelType = "Petrol"
}

class Scooter(override val maxSpeed: Int) : Vehicle {
    override val fuelType = "Electric"
}

fun main() {
    val m = Motorcycle(180)
    val s = Scooter(80)
    println("${m.fuelType}, electric: ${m.isElectric}")  // Petrol, electric: false
    println("${s.fuelType}, electric: ${s.isElectric}")  // Electric, electric: true
}

Practical Example: Notification System

interface Notifiable {
    val recipient: String
    fun notify(message: String)
}

interface Loggable {
    fun log(event: String) = println("[LOG] $event at ${System.currentTimeMillis()}")
}

class EmailNotifier(override val recipient: String) : Notifiable, Loggable {
    override fun notify(message: String) {
        println("EMAIL to $recipient: $message")
        log("Email sent to $recipient")
    }
}

class SMSNotifier(override val recipient: String) : Notifiable, Loggable {
    override fun notify(message: String) {
        println("SMS to $recipient: $message")
        log("SMS sent to $recipient")
    }
}

fun main() {
    val notifiers: List = listOf(
        EmailNotifier("alice@mail.com"),
        SMSNotifier("+91-9876543210")
    )
    notifiers.forEach { it.notify("Your order has been shipped!") }
}

Leave a Comment

Your email address will not be published. Required fields are marked *