Table of Contents
Why Functions Matter
In Kotlin, a function is a reusable block of code that performs a specific task. Functions help you avoid repeating the same code, make your programs easier to read, and let you organize logic into small, clear steps. In Android development, you will use functions for almost everything, from responding to button clicks to loading data from the internet.
In this chapter you will see how to declare and use functions in Kotlin, with an emphasis on what you will actually need when writing Android apps.
Basic Function Declaration
A simple function in Kotlin is created with the fun keyword, followed by the function name, a list of parameters in parentheses, and a return type.
fun sayHello() {
println("Hello")
}
This function has no parameters and returns nothing. In Kotlin the type Unit represents “no meaningful value,” similar to void in some other languages. You usually omit : Unit because Kotlin can infer it.
The general form of a function looks like this:
fun functionName(parameterName: Type, another: Type): ReturnType {
// function body
}To call a function, you simply write its name followed by parentheses:
sayHello()Parameters and Return Types
Functions can receive data through parameters and can send a result back through a return type.
Here is a function that accepts two integers and returns their sum:
fun add(a: Int, b: Int): Int {
return a + b
}When you call it, you pass arguments:
val result = add(3, 5) // result is 8Kotlin always specifies parameter types explicitly, and the return type appears after a colon following the parameter list.
If a function does not need to return a value, you can write it with no return type and Kotlin will treat it as returning Unit:
fun logMessage(message: String) {
println(message)
}
You can always write : Unit, but in everyday code you do not.
Expression Body Functions
When the function body is a single expression, you can use a more compact syntax, called an expression body. This is common in Android when writing small helper functions.
For example, the previous add function can be written as:
fun add(a: Int, b: Int): Int = a + b
You remove the braces and the return keyword, and use = followed by an expression. The expression result is automatically returned.
Kotlin can infer the return type if it is clear from the expression, so you can write:
fun add(a: Int, b: Int) = a + b
Here Kotlin infers that the return type is Int. This style is very useful for small functions such as formatting text for display in a TextView or converting numbers to strings.
Prefer expression body functions for short, single-expression logic, especially when they improve readability. Use the full block body with { } when the logic is longer or needs multiple steps.
Named and Default Arguments
When you call a function, you usually pass arguments in the order the parameters are declared. Kotlin also allows named arguments, which can make code more readable, especially when there are many parameters or several of the same type.
fun showUserInfo(name: String, age: Int, isPremium: Boolean) {
println("Name: $name, age: $age, premium: $isPremium")
}
// Positional arguments
showUserInfo("Alice", 30, true)
// Named arguments
showUserInfo(
name = "Alice",
age = 30,
isPremium = true
)Named arguments are useful in Android when functions have many optional settings, such as building a notification or configuring a view.
Kotlin also supports default parameter values. This lets you skip some arguments when you call the function.
fun showUserInfo(
name: String,
age: Int = 0,
isPremium: Boolean = false
) {
println("Name: $name, age: $age, premium: $isPremium")
}
showUserInfo("Bob") // age = 0, isPremium = false
showUserInfo("Carol", isPremium = true)
Here the second call uses the default value for age, and only overrides isPremium.
Use default parameter values instead of creating multiple functions with similar signatures only to provide optional values. This reduces code duplication and makes APIs easier to use.
Single Expression Utility Functions in Android
In Android, you will often define small utility functions that format or transform data before showing it in the UI. Expression body syntax combines well with string templates.
For example:
fun formatUserGreeting(name: String) = "Welcome, $name!"
fun calculateDiscountedPrice(price: Double, discount: Double) =
price * (1.0 - discount)
You might then use such a function when setting text in a TextView:
val greeting = formatUserGreeting("Maria")
// textView.text = greeting // You will see this style later in the courseThe focus here is creating clear, small functions that perform one task and return a value.
Overloading Functions
Kotlin allows you to create multiple functions with the same name but different parameter lists. This is called function overloading. It can be handy when you want to provide different ways to perform a similar operation.
fun showScore(score: Int) {
println("Score: $score")
}
fun showScore(score: Int, playerName: String) {
println("Score for $playerName: $score")
}The compiler decides which version to call based on the arguments you pass.
In Android, overloading is often used when you want to log or show a message in multiple formats, or when you want a similar action to work with different types of input.
Be careful not to create too many overloaded versions with ambiguous meanings, because that can make code harder to read.
Functions as Return Values and Local Functions
Sometimes you need helper logic that is used only inside another function. Kotlin lets you define functions inside functions. These are called local functions.
fun processScores(scores: List<Int>): Int {
fun isValid(score: Int): Boolean {
return score >= 0
}
var total = 0
for (score in scores) {
if (isValid(score)) {
total += score
}
}
return total
}
Here isValid is only visible inside processScores. Local functions are useful when you want to keep helper code close to where it is used, and you do not need it anywhere else.
You can also return a function from another function, or pass functions as parameters. That concept belongs to higher order functions, which you will use heavily with Android APIs, but the details will be covered later. For now, it is enough to know that in Kotlin functions are “first class,” which means they can be treated like values.
Top Level Functions vs Member Functions
In Kotlin, you can define functions at the top level of a file, outside any class, or inside a class as member functions.
A top level function:
// In a file named Utils.kt
fun formatScore(score: Int): String {
return "Score: $score"
}You can call it directly from other code in the same package once you import it if needed.
Member functions belong to a class or object and usually operate on that object’s data. You will use them when working with Android classes such as Activity and Fragment.
For example, a member function inside a class might look like this:
class ScoreManager {
private var score: Int = 0
fun increaseScore() {
score += 1
}
fun getScoreText(): String {
return "Score: $score"
}
}
You must create an instance of ScoreManager to call its functions:
val manager = ScoreManager()
manager.increaseScore()
val text = manager.getScoreText()Top level functions are convenient for general utilities, while member functions are used when behavior belongs to a specific type or object. As you work more with Android, you will see both styles in real apps.
Inline Functions and Performance Notes
Kotlin has a feature called inline functions, which is mostly relevant when you work with higher order functions and lambdas. Inline functions can help reduce overhead in some cases. The detailed explanation of inlining and performance belongs to more advanced parts of the course, so for now you only need to recognize that some library functions might be declared with the inline keyword.
From the perspective of writing beginner Android apps, you do not need to mark your own functions as inline. Focus instead on writing clear functions that do one thing well.
Organizing Functions in Android Projects
As your project grows, you will create many functions. Code becomes much easier to maintain when related functions are grouped logically.
In practice this means placing top level utility functions into files named after their purpose, such as StringExtensions.kt or DateUtils.kt, and member functions inside the relevant Activity, Fragment, ViewModel, or other class.
When you design a function, try to give it a clear, descriptive name. For example, loadUserProfile(), updateScoreDisplay(), or validateEmailInput(text: String): Boolean. The name should tell you what the function does, not how it does it inside.
Write functions that are short, focused, and clearly named. A good rule is that a function should do one thing, and its name should describe that thing without needing extra comments.
These habits will make your Android code more readable and testable, and they start with understanding and using functions well.