Kotlin, in depth
A from-the-ground-up Kotlin masterclass: essentials → OOP → coroutines → flows → an advanced type system. 47 lessons across 5 chapters, with live runnable Kotlin 1.8.20, inline visualizations, pitfall/deeper/tip/FAQ callouts, and stdin/stdout-graded practice.
Hello Kotlin → string templates → Int → integer division → val/var → floating-point → integer family → if/when expressions → Char → receipt capstone
- Step 1
Hello, Kotlin — your first program
Every Kotlin program starts at a single function: `fun main()`. When you run a file, the JVM finds `main` and calls it. …
Start lesson - Step 2
Strings, special characters & templates
A **string** is text in double quotes: `"hello"`. Some characters can't be typed literally inside quotes, so Kotlin uses…
Start lesson - Step 3
Whole numbers — the Int type
`Int` is Kotlin's default type for whole numbers. It's a 32-bit signed integer, so it holds values from `-2,147,483,648`…
Start lesson - Step 4
Integer division & the modulo trick
Here's the gotcha that trips up everyone: when both operands are `Int`, `/` does **integer division** — it throws away t…
Start lesson - Step 5
val vs var — immutability by default
Kotlin gives you two ways to name a value. `val` (from *value*) is a **read-only** binding — assign it once, and it can'…
Start lesson - Step 6
Floating-point numbers — Double & Float
For numbers with a fractional part, Kotlin uses **`Double`** (64-bit) by default and **`Float`** (32-bit) when you ask f…
Start lesson - Step 7
The integer family — Long, Int, Short, Byte
`Int` isn't the only whole-number type. Kotlin has four signed integer types of different widths: **`Byte`** (8-bit, ±12…
Start lesson - Step 8
if and when are expressions
In many languages `if` is a *statement* — it does something but produces no value. In Kotlin, **`if` is an expression**:…
Start lesson - Step 9
The Char type
A **`Char`** is a single character in **single** quotes: `'A'`, `'7'`, `'\n'`. Don't confuse it with a one-character `St…
Start lesson - Step 10
Capstone — a receipt printer
Time to combine the chapter. You've met `main`, string templates, `Int` and `Double`, integer vs. real division, `val`/`…
Start lesson
Ranges → for/while loops → when matching → lists, maps & sets → iteration → collection operations.
- Step 11
Loops — repeat & while
A **loop** runs a block of code more than once. Kotlin's simplest is **`repeat(n) { ... }`** — it runs the block exactly…
Start lesson - Step 12
The for loop & ranges
Kotlin's **`for`** loop iterates over anything that can be *iterated*: a range, a list, a string. There's no C-style `fo…
Start lesson - Step 13
Ranges, downTo & step
Ranges are richer than `a..b`. **`downTo`** counts backwards: `5 downTo 1` is `5,4,3,2,1`. **`step`** changes the stride…
Start lesson - Step 14
do-while & splitting input
A **`do { ... } while (cond)`** loop is `while`'s mirror image: it runs the body *first*, then checks the condition. The…
Start lesson - Step 15
Lists — the read-only basics
A **`List`** is an ordered collection of elements. Create one with **`listOf(...)`**: `val xs = listOf(10, 20, 30)`. The…
Start lesson - Step 16
MutableList — add, remove, change
When you genuinely need to grow, shrink, or edit a collection, use a **`MutableList`**, created with **`mutableListOf(..…
Start lesson - Step 17
Iterating with index & value
Often you need an element *and* its position: numbering a menu, formatting a table, comparing neighbours. **`list.withIn…
Start lesson - Step 18
break & continue
Two keywords steer a loop from the inside. **`break`** exits the loop immediately — no more iterations. **`continue`** s…
Start lesson - Step 19
Nested loops
A **nested loop** is a loop inside another loop. For every single pass of the outer loop, the inner loop runs *completel…
Start lesson - Step 20
Capstone — FizzBuzz
**FizzBuzz** is the most famous small programming exercise — and a perfect capstone for control flow. The rules: for the…
Start lesson
Classes, constructors, properties, methods, and visibility — the building blocks of Kotlin objects.
- Step 21
Classes & objects
A **class** is a blueprint that bundles **state** (properties) and **behaviour** (functions) into one named type. An **o…
Start lesson - Step 22
Functions & expression bodies
A **function** is a named, reusable block of behaviour: `fun square(n: Int): Int { return n * n }`. The parts are the `f…
Start lesson - Step 23
Parameters, defaults & named arguments
Functions can take **multiple parameters**, separated by commas: `fun rectArea(width: Int, height: Int) = width * height…
Start lesson - Step 24
this & calling methods
Inside a class, **`this`** refers to the current instance — the specific object the method was called on. Most of the ti…
Start lesson - Step 25
Primary constructors & init
The **primary constructor** is part of the class header. `class Account(val owner: String, var balance: Int)` declares t…
Start lesson - Step 26
Secondary constructors
Sometimes one class needs **more than one way to be built**. A **secondary constructor** — declared in the body with the…
Start lesson - Step 27
Member functions & encapsulation
**Member functions** (methods) are where a class's behaviour lives. They read and modify the instance's properties to en…
Start lesson - Step 28
Return types, Unit & multiple returns
A function's **return type** is declared after the parameter list: `fun max3(a: Int, b: Int, c: Int): Int`. It's a contr…
Start lesson - Step 29
Properties & default values
A **property** is a class's state. Declared in the primary constructor (`val`/`var`) or in the body (`val full = "$first…
Start lesson - Step 30
Capstone — BankAccount
Time to combine the chapter into one well-encapsulated class. A **`BankAccount`** holds a `balance` and exposes two oper…
Start lesson
open/override, abstract classes, interfaces, and polymorphic dispatch in Kotlin.
- Step 31
inline functions — the call site rewrite
A higher-order function that takes a lambda normally *costs* something at runtime: the lambda becomes an object (a `Func…
Start lesson - Step 32
reified — defeating type erasure
On the JVM, generics are **erased**: at runtime a `List<String>` and a `List<Int>` are both just `List`, and inside a ge…
Start lesson - Step 33
value classes — wrappers with no wrapper
You often want a *type* without a *cost*: a `UserId` that's really an `Int` but can't be mixed up with an `OrderId`, or …
Start lesson - Step 34
Variance — out, in & star projections
Generics raise a subtle question: if `Cat` is a `Animal`, is `List<Cat>` a `List<Animal>`? Naively yes, but that's unsaf…
Start lesson - Step 35
Smart casts — control-flow type narrowing
In many languages, after you check `if (x is String)` you still have to *cast* — `((String) x).length`. Kotlin tracks th…
Start lesson - Step 36
Contracts — teaching the flow analyzer
The flow analysis behind smart casts is powerful but *local*: it only sees code it can read directly. Call a helper like…
Start lesson - Step 37
Delegation — what `by` desugars into
Inheritance is one way to reuse behaviour, but it couples you tightly to a superclass. **Delegation** — 'has-a' instead …
Start lesson - Step 38
Property delegates — getValue, setValue, provideDelegate
`val name by lazy { compute() }` and `var x by Delegates.observable(...)` use the *other* `by` — **property delegation**…
Start lesson - Step 39
tailrec — recursion compiled to a loop
Recursion is elegant but dangerous on the JVM: each call consumes a stack frame, and a few thousand deep you hit `StackO…
Start lesson - Step 40
data classes — equals, hashCode, copy, componentN
Mark a class **`data`** and the compiler generates, from the properties in the **primary constructor**, the boilerplate …
Start lesson
Reading & writing files, richer collection pipelines, and behaviour-preserving refactoring.
- Step 41
Coroutine internals — the suspend state machine
A `suspend` function looks like it *blocks* and resumes, but the JVM has no built-in way to pause a method mid-execution…
Start lesson - Step 42
Sealed classes & exhaustive when
A **`sealed`** class (or interface) declares a **closed** set of subtypes: every direct subclass must be declared in the…
Start lesson - Step 43
Extension functions & receivers
An **extension function** lets you add a method to a type you don't own — `String`, `List`, a library class — *without i…
Start lesson - Step 44
Scope functions — let, run, with, apply, also
The five **scope functions** — `let`, `run`, `with`, `apply`, `also` — all execute a lambda *in the context of an object…
Start lesson - Step 45
Sequences — lazy, element-by-element pipelines
Chaining `map`/`filter` on a **`List`** is **eager**: each operation runs to completion over the whole collection and al…
Start lesson - Step 46
Null safety — ?., ?:, !! and let
Kotlin splits every type into **non-null** (`String`) and **nullable** (`String?`). A non-null type *cannot* hold `null`…
Start lesson - Step 47
Enum classes — constants with state & behaviour
An **`enum class`** defines a fixed, finite set of named constant instances — `Direction.NORTH`, `Direction.SOUTH`, … — …
Start lesson