Kotlin Cheatsheet

1. Variables and Data Types

val age: Int = 30  // Immutable
var name: String = "John"  // Mutable
val isStudent = true  // Type inference

// Nullable types
var middleName: String? = null

// Collections
val numbers: List<Int> = listOf(1, 2, 3)
val mutableNumbers: MutableList<Int> = mutableListOf(1, 2, 3)

2. Control Flow (Conditionals and Loops)

// If-else expression
val max = if (a > b) a else b

// When statement (replacement for switch)
val result = when (day) {
  1 -> "Monday"
  2 -> "Tuesday"
  else -> "Other day"
}

// Loops
for (i in 1..5) {
  println(i)
}

for (i in numbers) {
  println(i)
}

// Ranges
for (i in 1..10 step 2) {
  println(i)
}

while (age < 40) {
  println(age)
  age++
}

3. Functions and Higher-Order Functions

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

// Single-expression function
fun add(a: Int, b: Int) = a + b

// Higher-order functions
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
  return operation(a, b)
}
val result = operate(5, 10, ::add)
println(result)  // 15

// Lambda expression
val multiply = { x: Int, y: Int -> x * y }
println(multiply(5, 10))

4. Object-Oriented Programming (OOP)

open class Animal(val name: String) {
  open fun speak() {
    println("\$name makes a sound.")
  }
}

class Dog(name: String) : Animal(name) {
  override fun speak() {
    println("\$name barks.")
  }
}

val rex = Dog("Rex")
rex.speak()

// Inheritance
class Cat(name: String) : Animal(name) {
  override fun speak() {
    println("\$name meows.")
  }
}

// Properties and Custom Getters/Setters
class Person(var age: Int) {
  var name: String = ""
    get() = field.capitalize()
    set(value) {
      field = value.trim()
    }
}

val person = Person(30)
person.name = " john "
println(person.name)  // John

5. Data Classes and Sealed Classes

// Data class (auto-generates equals(), hashCode(), and toString())
data class User(val name: String, val age: Int)

val user = User("John", 30)
println(user)

// Sealed class (restricted class hierarchy)
sealed class Result {
  data class Success(val data: String) : Result()
  data class Error(val error: String) : Result()
}

val result: Result = Result.Success("Data loaded")
when (result) {
  is Result.Success -> println(result.data)
  is Result.Error -> println(result.error)
}

6. Extensions and Inline Functions

// Extension function
fun String.shout() = this.uppercase()

val message = "hello"
println(message.shout())  // HELLO

// Inline function
inline fun <T> lock(lock: Lock, action: () -> T): T {
  lock.lock()
  try {
    return action()
  } finally {
    lock.unlock()
  }
}

7. Coroutines and Concurrency

import kotlinx.coroutines.*

fun main() = runBlocking {
  launch {
    delay(1000L)
    println("Hello from coroutine!")
  }
  println("Hello from main")
}

// Async and Await
val deferred = async {
  delay(2000L)
  "Result"
}
println("Waiting for result...")
println(deferred.await())

// CoroutineScope and Dispatchers
launch(Dispatchers.IO) {
  // Run a blocking IO operation here
}

8. Collections and Functional Programming

// Functional programming in Kotlin (map, filter, reduce)
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
val evenNumbers = numbers.filter { it % 2 == 0 }
val sum = numbers.reduce { acc, number -> acc + number }

println(doubled)
println(evenNumbers)
println(sum)

// FlatMap and GroupBy
val nestedNumbers = listOf(listOf(1, 2), listOf(3, 4))
val flatList = nestedNumbers.flatten()

val groupedByEvenOdd = numbers.groupBy { it % 2 == 0 }
println(flatList)
println(groupedByEvenOdd)

9. Null Safety and Safe Calls

// Null safety
var middleName: String? = null

// Safe calls
println(middleName?.uppercase())  // Prints null instead of throwing exception

// Elvis operator (?:)
val fullName = middleName ?: "No middle name"
println(fullName)

// Not-null assertion (!!)
println(middleName!!.uppercase())  // Throws NullPointerException if null

10. Type Aliases and Generics

// Type alias
typealias EmployeeMap = Map<String, Employee>
val employees: EmployeeMap = mapOf("John" to Employee("John"))

// Generics
class Box<T>(val value: T) {
  fun getValue(): T = value
}

val box = Box(10)
println(box.getValue())  // 10

// Variance (in, out)
class Container<out T>(val value: T)
val stringContainer: Container<String> = Container("Hello")
val anyContainer: Container<Any> = stringContainer  // Covariance

11. Delegation and Lazy Initialization

// Delegated properties
class Person {
  var name: String by Delegates.observable("") { _, old, new ->
    println("Name changed from $old to $new")
  }
}

val person = Person()
person.name = "John"

// Lazy initialization
val lazyValue: String by lazy {
  println("Computed!")
  "Hello, Lazy!"
}
println(lazyValue)
println(lazyValue)  // Second call doesn't compute

12. Kotlin JVM and Interoperability with Java

// Calling Kotlin from Java
fun greet(name: String): String = "Hello, $name"

// Calling Java from Kotlin
val list = ArrayList<String>()  // Java's ArrayList
list.add("John")
println(list)

13. Exception Handling and Try-Catch

try {
  val result = 10 / 0
} catch (e: ArithmeticException) {
  println("Error: Division by zero")
} finally {
  println("This always runs")
}

// Custom exceptions
class InvalidAgeException(message: String) : Exception(message)

fun validateAge(age: Int) {
  if (age < 18) throw InvalidAgeException("Age must be greater than 18")
}

try {
  validateAge(16)
} catch (e: InvalidAgeException) {
  println(e.message)
}