Extension Functions
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 30 of 57.
An extension function adds a function to an existing type without changing the type's source code. Its name is written after the receiver type, and inside it this refers to the receiver, which can also be left out:
fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0Inside main:
println("hello".shout())
println(7.isEven())
println(listOf(1, 2, 3, 4).count { it.isEven() })Output:
HELLO!
false
2Extensions work on your own classes too, and extension properties add computed properties. An extension cannot add stored state, and it only reaches the public members of its receiver:
class Temperature(val celsius: Double)
val Temperature.fahrenheit: Double
get() = celsius * 9 / 5 + 32
fun Temperature.describe() = "$celsius C is $fahrenheit F"Inside main:
println(Temperature(100.0).describe())Output:
100.0 C is 212.0 FExtensions are resolved statically: the declared type of the expression picks the extension when the program is compiled, not the object's class. This is the main difference from an overridden member:
open class Shape {
open fun member() = "shape member"
}
class Circle : Shape() {
override fun member() = "circle member"
}
fun Shape.ext() = "shape extension"
fun Circle.ext() = "circle extension"Inside main:
val s: Shape = Circle()
println(s.member())
println(s.ext())Output:
circle member
shape extensionWhen the class already has a member with the same signature, the member always wins. Use members for behaviour that belongs to the type and may be overridden; use extensions for helpers added from outside, such as formatting for a class you do not own:
class Robot {
fun greet() = "member greet"
}
fun Robot.greet() = "extension greet"
fun Robot.wave() = "extension wave"Inside main:
val r = Robot()
println(r.greet())
println(r.wave())Output:
member greet
extension waveChallenge
EasyMoney(cents) is supplied in Money.kt. Write extensions for it in MoneyExtensions.kt: the extension properties Int.dollars and Int.cents, which turn a number into Money (12.dollars is 1200 cents), Money.format(), which returns $12.50 (or -$3.05 for negative amounts), List<Money>.total(), which returns the sum as Money, and Money.split(parts), which splits into parts amounts that differ by at most one cent, with the larger ones first.
The supplied code reads lines 12 dollars or 50 cents and a last line with the number of parts. It prints every amount, total: $12.50 and split 3: $4.17 $4.17 $4.16.
Your code goes in MoneyExtensions.kt and Money.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 amounts = input.dropLast(1).map { line ->
val (n, unit) = line.split(" ")
if (unit == "dollars") n.toInt().dollars else n.toInt().cents
}
for (m in amounts) println(m.format())
val total = amounts.total()
println("total: ${total.format()}")
val parts = input.last().toInt()
println("split $parts: " + total.split(parts).joinToString(" ") { it.format() })
}
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 Books3Objects and Companions
Object DeclarationsCompanion ObjectsConstants With constObject ExpressionsRecap - Ticket Office6Polymorphism
Dynamic DispatchType Checks and Smart Castswhen With TypesExtension FunctionsRecap - Zoo KeeperPractice on your own: Kotlin playground