Default Methods
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 23 of 57.
An interface method can have a body. This default implementation is used by every class that does not override it:
interface Greeter {
val name: String
fun greet() = "Hello, I am $name"
}
class Robot(override val name: String) : Greeter
class Pirate(override val name: String) : Greeter {
override fun greet() = "Ahoy! $name here"
}Inside main:
println(Robot("R2").greet())
println(Pirate("Anne").greet())Output:
Hello, I am R2
Ahoy! Anne hereDefault methods are written in terms of the interface's other members. A class provides the few members that differ and receives the rest:
interface Priced {
val cents: Int
fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
fun isAffordable(budget: Int) = cents <= budget
}
class Coffee : Priced {
override val cents = 450
}Inside main:
val c = Coffee()
println(c.formatted())
println(c.isAffordable(400))Output:
$4.50
falseProperties can have a default getter, but an interface has no backing fields, so it cannot store a value. A property with an initializer does not compile; a getter that computes the value does:
interface Box {
val width: Int
val height: Int
val area: Int
get() = width * height
// val count = 0 // error: property initializers are not allowed in interfaces
}
class Tile(override val width: Int, override val height: Int) : BoxInside main:
println(Tile(3, 4).area)Output:
12An override can still use the default implementation. Inside the class, super.method() calls the interface's version:
interface Priced {
val cents: Int
fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
}
class Coffee : Priced {
override val cents = 450
override fun formatted() = "coffee " + super.formatted()
}Inside main:
println(Coffee().formatted())Output:
coffee $4.50Challenge
EasyThe interface Priced has price (in cents). Give it a default formatted() that returns $4.50 and a default isAffordable(budget) that returns whether the price is at most the budget. Coffee costs 450 and replaces formatted() with coffee $4.50, reusing the default through super. Sandwich(price) uses both defaults.
The supplied code reads a budget in cents and then lines coffee or sandwich,650. It prints formatted() and yes or no for each item.
Your code goes in Priced.kt, Coffee.kt and Sandwich.kt. Main.kt holds the supplied input/output code and cannot be edited.
Try it yourself
fun main() {
// Supplied input/output code: keep it as it is
val input = generateSequence(::readLine).toList()
val budget = input[0].toInt()
for (line in input.drop(1)) {
val p = line.split(",")
val item: Priced = if (p[0] == "coffee") Coffee() else Sandwich(p[1].toInt())
println("${item.formatted()} ${if (item.isAffordable(budget)) "yes" else "no"}")
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesPrimary Constructorsinit Blocks and ValidationSecondary ConstructorsRecap - Library Card4Inheritance
Open Classes and SubclassesOverriding Memberssuper and ConstructorsAbstract ClassesRecap - Staff Directory2Properties and Encapsulation
Custom AccessorsVisibility ModifiersPrivate Setterslazy and lateinitRecap - Bank Account5Interfaces
Declaring InterfacesDefault MethodsMultiple InterfacesInterfaces as TypesRecap - Payment Methods8Generics
Generic FunctionsGeneric ClassesType ConstraintsVariance With in and outRecap - Priority Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Kotlin playground