Kotlin Interface Keyword
last modified April 19, 2025
Kotlin interfaces define contracts that classes can implement. They can contain
abstract methods and properties, as well as default implementations. Interfaces
enable polymorphism and multiple inheritance in Kotlin. This tutorial explores
the interface keyword in depth with practical examples.
Basic Definitions
An interface in Kotlin is a blueprint of a class. It contains abstract method
declarations and method implementations. Interfaces cannot store state but can
have properties. Classes implement interfaces using the : syntax.
Multiple interfaces can be implemented by a single class.
Basic Interface Declaration
The simplest interface contains abstract method declarations. Classes implementing the interface must provide concrete implementations for these methods. This enforces a contract that implementing classes must follow.
package com.zetcode
interface Greeter {
fun greet(): String
}
class Person : Greeter {
override fun greet(): String {
return "Hello!"
}
}
fun main() {
val person = Person()
println(person.greet()) // Output: Hello!
}
Here we define a Greeter interface with one abstract method. The
Person class implements this interface and provides the method
body. The override keyword is required when implementing interface
methods.
Interface with Default Implementation
Kotlin interfaces can provide default implementations for methods. Classes implementing the interface can use these defaults or override them. This feature makes interfaces more flexible than abstract classes in some cases.
package com.zetcode
interface Vehicle {
fun start() {
println("Vehicle started")
}
fun stop()
}
class Car : Vehicle {
override fun stop() {
println("Car stopped")
}
}
fun main() {
val car = Car()
car.start() // Output: Vehicle started
car.stop() // Output: Car stopped
}
The Vehicle interface provides a default implementation for
start but leaves stop abstract. The Car
class only needs to implement stop and inherits the default
start behavior.
Interface Properties
Interfaces can declare abstract properties that implementing classes must provide. These properties can be implemented as fields or through getters. Interface properties cannot have backing fields but can have custom accessors.
package com.zetcode
interface User {
val name: String
val age: Int
get() = 0 // Default implementation
}
class RegisteredUser(override val name: String) : User {
// age uses default implementation
}
fun main() {
val user = RegisteredUser("John Doe")
println("${user.name}, ${user.age}") // Output: John Doe, 0
}
The User interface declares two properties. name is
abstract and must be implemented, while age has a default value.
The RegisteredUser class implements name as a property
and uses the default age implementation.
Multiple Interface Implementation
Kotlin supports multiple interface inheritance. A class can implement several interfaces, inheriting all their members. If there are method conflicts, the implementing class must resolve them explicitly.
package com.zetcode
interface Flyable {
fun fly() {
println("Flying high")
}
}
interface Swimmable {
fun swim() {
println("Swimming deep")
}
}
class Duck : Flyable, Swimmable {
fun describe() {
fly()
swim()
}
}
fun main() {
val duck = Duck()
duck.describe()
// Output:
// Flying high
// Swimming deep
}
The Duck class implements both Flyable and
Swimmable interfaces. It can call methods from both interfaces.
This demonstrates Kotlin's support for multiple inheritance of behavior through
interfaces.
Resolving Method Conflicts
When multiple interfaces declare methods with the same signature, implementing classes must resolve the conflict. This is done by overriding the method and specifying which interface's implementation to use.
package com.zetcode
interface A {
fun foo() {
println("A's foo")
}
}
interface B {
fun foo() {
println("B's foo")
}
}
class C : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
println("C's foo")
}
}
fun main() {
val c = C()
c.foo()
// Output:
// A's foo
// B's foo
// C's foo
}
The C class implements both A and B which
have conflicting foo methods. The class resolves this by calling
both implementations using super<Interface> syntax and adding
its own behavior.
Functional Interfaces (SAM Interfaces)
Single Abstract Method (SAM) interfaces can be implemented using lambdas. These
are called functional interfaces in Kotlin. The fun modifier marks
an interface as functional.
package com.zetcode
fun interface StringProcessor {
fun process(input: String): String
}
fun main() {
val upperCaseProcessor = StringProcessor { it.uppercase() }
val lowerCaseProcessor = StringProcessor { it.lowercase() }
println(upperCaseProcessor.process("Hello")) // Output: HELLO
println(lowerCaseProcessor.process("World")) // Output: world
}
The StringProcessor interface is marked with fun making
it a functional interface. We create instances using lambdas instead of full
class implementations. This provides concise syntax for simple interface
implementations.
Interface Inheritance
Interfaces can inherit from other interfaces, forming interface hierarchies. The child interface includes all members of its parent interfaces. Implementing classes must satisfy all requirements from the entire hierarchy.
package com.zetcode
interface Animal {
fun eat()
}
interface Mammal : Animal {
fun nurse()
}
class Human : Mammal {
override fun eat() {
println("Eating food")
}
override fun nurse() {
println("Nursing young")
}
}
fun main() {
val human = Human()
human.eat() // Output: Eating food
human.nurse() // Output: Nursing young
}
The Mammal interface extends Animal, inheriting its
eat method. The Human class implements Mammal
and must provide implementations for both eat and nurse.
This shows how interface hierarchies work in Kotlin.
Best Practices for Interfaces
- Prefer interfaces to abstract classes: Use interfaces for defining contracts when possible, as they support multiple inheritance.
- Use default implementations wisely: Provide default implementations for methods that have common behavior across implementations.
- Keep interfaces focused: Follow the Interface Segregation Principle - interfaces should be small and focused.
- Document interface contracts: Clearly document what implementers must provide and what callers can expect.
- Consider functional interfaces: Use SAM interfaces when a single abstract method is sufficient for the contract.
Source
Kotlin Interfaces Documentation
This tutorial covered Kotlin's interface keyword in depth, showing
basic declarations, default methods, properties, and multiple inheritance. We
explored various scenarios including method conflicts and functional interfaces.
Proper use of interfaces can make your code more flexible and maintainable.
Author
List all Kotlin tutorials.