What an interface is
An interface lists what a class can do without saying how it does it. A Dog, a Robot and a Drone are different kinds of things, yet each might be able to speak or move. If the ability is written as an interface, any class can promise to provide it, and code that only needs the ability can work with all of them.
Inheritance models "is a" (a dog is an animal). An interface models "can do" (a dog can speak). The lesson's interface is one function with no body:
interface Speaker {
fun speak()
}
A function without a body in an interface is abstract, and every class that implements the interface must provide it. You don't write the keyword abstract here: inside an interface it is implied.
Step by step: the exercise
The lesson supplies the Speaker interface and a Solution class whose mainFunction creates val rex: Speaker = Dog() and calls rex.speak(). The output must be Woof, so you write the Dog class.
- Declare
Dogand listSpeakerafter a colon. Kotlin uses the same colon for extending a class and for implementing an interface. Note that there are no parentheses afterSpeaker: an interface has no constructor, so there is nothing to call. A class, by contrast, needs them, as in: Animal(). - Implement
speakwithoverride. Writeoverride fun speak()and printWoofwithprintln. The keyword is mandatory in Kotlin, which makes it clear that the function comes from a contract.
The variable is declared as Speaker but holds a Dog. The call rex.speak() is allowed because Speaker has speak(), and it runs the version in Dog.
The solution in Kotlin
interface Speaker {
fun speak()
}
class Dog : Speaker {
override fun speak() {
println("Woof")
}
}
class Solution {
fun mainFunction() {
val rex: Speaker = Dog()
rex.speak()
}
}
Three details here are easy to trip over:
- No constructor call for an interface. Writing
class Dog : Speaker()fails withthis type does not have a constructor. And creating an interface directly, as inSpeaker(), fails withinterface 'interface Speaker : Any' does not have constructors. overrideis not optional. Afun speak()inDogwithout it gives'speak' hides member of supertype 'Speaker' and needs an 'override' modifier.- Missing implementations are errors. A class that lists
Speakerbut has nospeak()getsclass 'Cat' is not abstract and does not implement abstract member.
One class, many interfaces
A Kotlin class has at most one superclass but can implement as many interfaces as it likes. List them after the colon, separated by commas:
interface Speaker { fun speak() }
interface Named { val name: String }
class Dog : Speaker, Named {
override val name = "Rex"
override fun speak() { println("Woof") }
}
class Robot : Speaker {
override fun speak() { println("Beep") }
}
fun greet(s: Speaker) = s.speak()
fun main() {
greet(Dog())
greet(Robot())
}
This prints Woof and then Beep. The function greet accepts anything that is a Speaker. It doesn't know or care whether it received a dog or a robot, and a new class can be added later without changing greet. The example also shows that an interface can declare a property, here name, which the class overrides.
Interface versus abstract class
| Abstract class | Interface | |
|---|---|---|
| Constructor and stored state | Yes | No stored state |
| Members with bodies | Yes | Yes, as default implementations |
| How many a class can use | One parent | Any number |
| Models | "is a" | "can do" |
Kotlin interfaces may contain functions with bodies, which act as defaults. A class can use them as they are or override them:
interface Mover {
fun move() = println("moving")
}
If two interfaces give the same function a default body and a class implements both, the compiler stops you with class 'C' must override 'hi' because it inherits multiple interface methods for it. The class resolves it by overriding the function and choosing which parent to call with super<A>.hi().
Common mistakes
- Parentheses after the interface name. They belong only after a class in the supertype list.
- Leaving out
override. The compiler treats the function as a clash with the interface's. - Forgetting a member. Implement every function and property that has no default.
- Trying to create an interface instance. Create the implementing class, and use the interface as the variable's type.
- Wrong output text. The lesson expects exactly
Woof.
Key takeaways
- An interface is a contract of "can do" members, declared with
interface. - A class implements it with a colon, no parentheses, and marks each implementation
override. - A class can implement many interfaces but extend only one class.
- A variable typed as the interface can hold any implementing object, and calls run that object's version.