Skip to content
ioob.dev
Go back

Kotlin Beginner Part 3 — Functions

· 2 min read
Kotlin Series (3/12)
  1. Kotlin Beginner Part 1 — Variables and Types
  2. Kotlin Beginner Part 2 — Conditionals and Loops
  3. Kotlin Beginner Part 3 — Functions
  4. Kotlin Beginner Part 4 — Classes and Objects
  5. Kotlin Beginner Part 5 — Collections and Lambdas
  6. Kotlin Part 6 — Null Safety Advanced
  7. Kotlin Part 7 — Generics
  8. Kotlin Part 8 — sealed class and enum
  9. Kotlin Part 9 — Coroutines Basics
  10. Kotlin Part 10 — Coroutines Advanced
  11. Kotlin Part 11 — DSL and Advanced Functions
  12. Kotlin Part 12 — Practical Patterns
Table of contents

Table of contents

Function Declaration

Kotlin functions are declared with the fun keyword.

fun greet(name: String): String {
    return "Hello, $name!"
}

The return type comes after a colon. If there’s no return value, it’s Unit, which can be omitted. It corresponds to Java’s void.

fun log(message: String) {  // : Unit is omitted
    println(message)
}

Default Parameters

If you’ve ever overloaded methods excessively in Java, Kotlin’s default parameters will be a welcome change.

fun createUser(
    name: String,
    age: Int = 0,
    role: String = "user"
): String {
    return "$name ($age, $role)"
}

This single function supports multiple calling styles.

createUser("Kim")                      // Kim (0, user)
createUser("Lee", 25)                  // Lee (25, user)
createUser("Park", 30, "admin")        // Park (30, admin)

In Java, you’d need a separate overloaded method for each parameter combination. Kotlin solves it with default values alone.

Named Arguments

When there are many parameters, it’s easy to get confused about which value corresponds to which parameter at the call site. Named arguments make this clear.

createUser(
    name = "Kim",
    role = "admin",  // Skip age and specify only role
)

The key benefit is being able to skip intermediate parameters. Combined with default parameters, this enables flexible object creation without the builder pattern.

Single-Expression Functions

When a function body consists of a single expression, you can omit the curly braces and return.

// Regular form
fun double(x: Int): Int {
    return x * 2
}

// Single expression — same function in one line
fun double(x: Int) = x * 2

The return type can also be inferred, so it can be omitted. This is commonly used for simple conversion and utility functions.

However, readability suffers when the logic gets complex, so it’s best used only when it fits naturally on a single line.

Extension Functions

One of Kotlin’s most distinctive features. You can add methods to existing classes without inheriting from or modifying them.

// Add an isEmail function to String
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

fun main() {
    println("test@email.com".isEmail())  // true
    println("not-email".isEmail())        // false
}

Writing String.isEmail() lets you call it as if the method originally existed on the String class. this refers to the object the function was called on.

Here’s one more practical example.

// Add a Won (KRW) format to Int
fun Int.toWon(): String {
    return "\u20a9${String.format("%,d", this)}"
}

fun main() {
    println(50000.toWon())     // \u20a950,000
    println(1234567.toWon())   // \u20a91,234,567
}

Extension functions cannot access private members of the original class. Internally, they compile to static methods, so they don’t break the encapsulation of the original class.

While they look like member methods at the call site, here’s how they’re actually transformed at the JVM bytecode level.

flowchart LR
    Src["Syntax<br/>&quot;abc&quot;.isEmail()"] --> Comp[Kotlin Compiler]
    Comp --> Byte["JVM Bytecode<br/>StringUtilsKt.isEmail(&quot;abc&quot;)"]
    Byte --> Note[Static method call]
    Note --> Result[Result: Boolean]

This is especially useful when creating utility functions in Android development or Spring projects. Instead of StringUtils.isEmpty(str), you can write the more natural str.isEmpty().


The next part covers Kotlin classes and objects. We’ll see how much boilerplate data class eliminates and what role object plays.

-> Part 4: Classes and Objects


Related Posts

Share this post on:

Comments

Loading comments...


Previous Post
Kotlin Beginner Part 2 — Conditionals and Loops
Next Post
Kotlin Beginner Part 4 — Classes and Objects