Infix Extension Functions
In this page:
infix fun ReceiverType.functionName(param: Type): ReturnType {
return value
}
val result = receiver functionName argument
Writing an Infix Extension
Combining infix with fun ReceiverType.name(param: Type) adds an operator-like call syntax to an existing type, usable as receiver name argument.
Example: Writing an Infix Extension
infix fun Int.plusPercent(percent: Int): Int = this + (this * percent / 100)
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `price`, set to `100`
val price = 100
// Print "Price with 20% added: ${price plusPercent 20}" to the console, with a trailing newline
println("Price with 20% added: ${price plusPercent 20}")
}
Login to try C/C++/Java/PHP code in the editor
Building Readable Domain Logic
Infix extensions are often used to give domain-specific operations a natural, sentence-like reading, which can make specialized code much clearer than a plain method call.
Example: Building Readable Domain Logic
infix fun Int.daysAfter(startDay: Int): Int = (startDay + this) % 7
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `monday`, set to `1`
val monday = 1
// Print "3 days after Monday: ${3 daysAfter monday}" to the console, with a trailing newline
println("3 days after Monday: ${3 daysAfter monday}")
}
Login to try C/C++/Java/PHP code in the editor
Infix Extensions on Custom Types
Infix extensions work on your own classes too, letting you define natural-reading operations between instances of types you control.
Example: Infix Extensions on Custom Types
// Define a data class `Vector`
data class Vector(val x: Int, val y: Int)
infix fun Vector.dot(other: Vector): Int = x * other.x + y * other.y
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `v1`, set to `Vector(2, 3)`
val v1 = Vector(2, 3)
// Declare a read-only variable `v2`, set to `Vector(4, 5)`
val v2 = Vector(4, 5)
// Print "Dot product: ${v1 dot v2}" to the console, with a trailing newline
println("Dot product: ${v1 dot v2}")
}
Login to try C/C++/Java/PHP code in the editor
When to Avoid Infix Style
Infix notation reads best for operations that resemble a natural verb or relationship between two values; for anything else, a regular method call with a clear name is more appropriate.
combineWith() over infix style if the relationship being expressed isn't intuitive from the words alone.Example: When to Avoid Infix Style
infix fun String.repeatedTwice(separator: String): String = "$this$separator$this"
// Entry point: execution of the program starts here
fun main() {
// Print "Hi" repeatedTwice ", " to the console, with a trailing newline
println("Hi" repeatedTwice ", ")
}
Login to try C/C++/Java/PHP code in the editor
- Forgetting that an infix extension function still must take exactly one parameter, the same rule as any other infix function.
- Applying infix extension notation to operations that are not naturally symmetric or relational, hurting readability instead of helping.
- Not marking the extension function
infix, then being confused why the operator-like call syntaxa op bdoes not compile.
- Combining
infixwith an extension function lets an existing type gain a brand-new operator-like syntax. - The extension must still satisfy the infix requirement of exactly one parameter.
- Infix extensions are commonly used to create small domain-specific languages (DSLs) that read naturally.
- As with any infix function, this style should be reserved for operations that genuinely read like a natural relation.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: