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!") }
} 