COURSE ยท 12 LESSONS ยท 100% FREE
๐ŸŸฃ

Kotlin Programming

Modern language for Android, servers, and multiplatform. Null-safe, concise, and interoperable with Java.

0Lessons
0Code Examples
ZeroPrerequisites
0%
You've completed 0 of 12 lessons
J/โ†“ Next
K/โ†‘ Prev
Esc Collapse
/ Search
Foundations
01

Hello World & Setup

fun main() is the entry point. val for immutable, var for mutable. No semicolons needed.

fun main() {
    println("Hello, World!")
    val name = "Mayank"  // immutable
    var age = 15          // mutable
    println("$name is $age")
    println("${name.uppercase()}")
}
02

Variables & Types

val/var, String, Int, Double, Boolean, List, Map. Kotlin is null-safe by default.

fun main() {
    val name: String = "Mayank"
    val age: Int = 15
    val pi: Double = 3.14159
    val passed: Boolean = true

    // Null safety
    var safe: String = "hello"   // can't be null
    var nullable: String? = null   // can be null
    println(nullable?.uppercase() ?: "null")
    println(nullable!!.uppercase())  // will throw if null

    // Collections
    val nums = listOf(1, 2, 3, 4, 5)
    val mutable = mutableListOf(1, 2)
    mutable.add(3)
    val map = mapOf("a" to 1, "b" to 2)
    println(map["a"])
}
03

Functions

fun keyword. Named/default params. Single-expression functions. Lambda.

fun add(a: Int, b: Int): Int = a + b
fun greet(name: String, prefix: String = "Hello") = "$prefix, $name!"

// Lambda
val square = { x: Int -> x * x }
val multiply = { a: Int, b: Int -> a * b }

// High-order function
fun apply(n: Int, f: (Int) -> Int): Int = f(n)

fun main() {
    println(add(3, 4))
    println(greet("Mayank"))
    println(greet("World", "Hi"))
    println(square(5))
    println(apply(10, square))

    val nums = listOf(1, 2, 3, 4, 5)
    println(nums.filter { it % 2 == 0 })
    println(nums.map { it * 10 })
    println(nums.reduce { a, b -> a + b })
}
04

Control Flow

if/else returns values. when is a super switch. for-in, while. Ranges (1..10, 1 until 10).

fun main() {
    val score = 85
    val grade = if (score >= 90) "A" else if (score >= 80) "B" else "C"
    println(grade)

    // when (switch on steroids)
    val day = 3
    when (day) {
        1 -> println("Monday")
        2 -> println("Tuesday")
        3 -> println("Wednesday")
        in 6..7 -> println("Weekend")
        else -> println("Other")
    }

    // Ranges
    for (i in 1..5) print("$i ")
    println()
    for (i in 1 until 10 step 2) print("$i ")
    println()

    // Destructuring
    data class Point(val x: Int, val y: Int)
    val p = Point(3, 4)
    val (x, y) = p
    println("($x, $y)")
}
05

Null Safety

?. safe call, !! non-null assertion, ?: Elvis operator, let, require/check.

fun main() {
    var name: String? = null

    // Safe call
    println(name?.length)  // null

    // Elvis operator
    println(name?.length ?: 0)  // 0

    // Non-null assertion (crashes if null!)
    // println(name!!.length)  // NullPointerException

    // let (only runs if not null)
    name = "Mayank"
    name?.let {
        println("Length: ${it.length}")
    }

    // require / check
    fun validate(age: Int) {
        require(age > 0) { "Age must be positive" }
        require(age < 150) { "Age too high" }
        println("Valid age: $age")
    }
    validate(15)

    // Smart cast after check
    val obj: Any = "hello"
    if (obj is String) {
        println(obj.length)  // auto-cast to String
    }
}
OOP & Functions
06

Classes & Data Classes

data class auto-generates equals/hashCode/toString. sealed class for restricted hierarchies.

data class Point(val x: Double, val y: Double) {
    fun distanceTo(other: Point) =
        Math.sqrt((x-other.x).pow(2) + (y-other.y).pow(2))
}

sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val msg: String) : Result()
}

fun main() {
    val p1 = Point(0.0, 0.0)
    val p2 = Point(3.0, 4.0)
    println(p1)  // Point(x=0.0, y=0.0)
    println(p1.distanceTo(p2))  // 5.0

    val r: Result = Result.Success("ok")
    when (r) {
        is Result.Success -> println(r.data)
        is Result.Error -> println(r.msg)
    }
}
07

Inheritance & Interfaces

open class (not final by default). Interface with default implementations. Abstract classes.

open class Animal(val name: String) {
    open fun speak() = "..."
}

class Dog(name: String) : Animal(name) {
    override fun speak() = "Woof!"
}

class Cat(name: String) : Animal(name) {
    override fun speak() = "Meow!"
}

interface Swimmable {
    fun swim() = println("Swimming!")
}

class Fish(name: String) : Animal(name), Swimmable

fun main() {
    val animals = listOf(Dog("Rex"), Cat("Whiskers"), Fish("Nemo"))
    for (a in animals) println("${a.name}: ${a.speak()}")

    val fish = Fish("Nemo")
    fish.swim()
}
08

Generics

Type parameters <T>. Constrain with : UpperBound. reified for runtime type info.

class Stack<T> {
    private val items = mutableListOf<T>()
    fun push(item: T) { items.add(item) }
    fun pop(): T? = items.removeLastOrNull()
    fun peek(): T? = items.lastOrNull()
}

fun <T> findMax(list: List<T>): T where T : Comparable<T> {
    return list.max()
}

inline fun <reified T> List<Any>.filterType(): List<T> {
    return filterIsInstance<T>()
}

fun main() {
    val stack = Stack<Int>()
    stack.push(1)
    stack.push(2)
    println(stack.pop())

    println(findMax(listOf(3, 1, 4, 1, 5)))

    val mixed = listOf(1, "hello", 3.14, "world")
    println(mixed.filterType<String>())  // [hello, world]
}
09

Extension Functions

Add methods to existing classes without modifying them. infix functions. operator overloading.

// Extension function
fun String.isPalindrome(): Boolean {
    val s = this.lowercase()
    return s == s.reversed()
}

fun Int.isEven() = this % 2 == 0

// Infix function
infix fun Int.power(exponent: Int): Long {
    var result = 1L
    repeat(exponent) { result *= this }
    return result
}

// Operator overloading
data class Vec2(val x: Int, val y: Int) {
    operator fun plus(other: Vec2) = Vec2(x + other.x, y + other.y)
    operator fun times(s: Int) = Vec2(x * s, y * s)
}

fun main() {
    println("racecar".isPalindrome())
    println(42.isEven())
    println(2 power 10)  // 1024
    println(Vec2(1,2) + Vec2(3,4))  // Vec2(x=4, y=6)
}
Advanced
10

Coroutines

async/await, Flow, channels. Lightweight concurrency without callback hell.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun fetchUser(): String {
    delay(1000)
    return "Mayank"
}

fun numberFlow() = flow {
    for (i in 1..5) {
        delay(500)
        emit(i)
    }
}

fun main() = runBlocking {
    // Launch concurrent
    val job = launch {
        val user = fetchUser()
        println("User: $user")
    }

    // Async
    val deferred = async { 42 * 42 }
    println("Result: ${deferred.await()}")

    // Flow
    numberFlow()
        .filter { it % 2 == 0 }
        .map { it * 10 }
        .collect { println(it) }

    job.join()
}
11

DSL & Type-Safe Builders

Kotlin's killer feature. Build HTML, SQL, configs with type-safe builders.

// HTML builder
class HTML {
    private val sb = StringBuilder()
    fun body(init: HTML.() -> Unit) {
        sb.append("<body>")
        init()
        sb.append("</body>")
    }
    fun p(text: String) { sb.append("<p>$text</p>") }
    override fun toString() = sb.toString()
}

fun html(init: HTML.() -> Unit) = HTML().apply(init)

fun main() {
    val page = html {
        body {
            p("Hello, World!")
            p("Kotlin DSLs are awesome")
        }
    }
    println(page)

    // Scope functions
    data class Config(var host: String = "", var port: Int = 0)
    val config = Config().apply {
        host = "localhost"
        port = 8080
    }
    println(config)
}
12

Multiplatform & Android

Share code between iOS, Android, web, desktop. Ktor for servers. Compose for UI.

// Ktor server (build.gradle.kts)
// implementation("io.ktor:ktor-server-core:2.3.0")
// implementation("io.ktor:ktor-server-netty:2.3.0")

fun main() = embeddedServer(Netty, port = 8080) {
    routing {
        get("/") { call.respondText("Hello, Ktor!") }
        get("/users") {
            call.respond(mapOf("users" to listOf("Mayank")))
        }
    }
}.start(wait = true)

// Compose Multiplatform
// @Composable
// fun App() {
//     var count by remember { mutableStateOf(0) }
//     Column {
//         Text("Count: $count")
//         Button(onClick = { count++ }) { Text("Increment") }
//     }
// }
//
// fun main() = application {
//     Window(onCloseRequest = ::exitApplication) {
//         App()
//     }
// }