Type Checking at Compile-Time, immutable, mutable:

val name = "range" // Immutable
var age = 30 // Mutable
var count: Int = 10

Late Initialisation or null(var only):

lateinit var description: String

fun setup(){
    description = "haha"
}

var name:String? = null

safe call:

// ?. must always be placed between an object and a member access (like .).

// It is not a standalone null-check operator.

// Often combined with the Elvis operator (?:) to provide a default value:

val len = user.name?.length ?: 0

not-null assertion operator

//  !!
// If the value is not null, execution continues normally.
// If the value is null, a NullPointerException (NPE) is thrown at runtime.
val name: String? = null
val len = name!!.length   // NullPointerException

Function definition

fun functionName(param1: Type1, param2: Type2): ReturnType {
    // body
    return value
}
// you may use Unit to replace the ReturnType. This means there is no return value 

// or you can write in this form is this is a one-line-func
fun square(x: Int): Int = x * x

// Default Arguments
fun greet(name: String = "Guest") {
    println("Hello, $name")
}

// Named Arguments (para passing)
fun register(name: String, age: Int, email: String) { }
register(age = 20, name = "Tom", email = "[email protected]")

// Vararg
fun sum(vararg numbers: Int): Int {
    return numbers.sum()
}
val total = sum(1, 2, 3, 4)  // 10

control flow

// when,  a better switch
when (x) {
    1 -> println("One")
    in 2..5 -> println("Between 2 and 5")
    is String -> println("It’s a String")
    else -> println("Other")
}
// for
for (i in 1..5) println(i)          // 1 2 3 4 5
for (i in 10 downTo 1 step 3) print("$i ") // 10 7 4 1
for (item in listOf("a","b")) println(item)
// while

var i = 3
while (i > 0) {
    println(i)
    i--
}


// do...while
var i = 0
do {
    println(i)
    i++
} while (i < 3)

class

// =========================
// 1. Class Declaration
// =========================
class Person {
    var name: String = "Unknown"   // mutable property
    fun sayHello() = println("Hello, I’m $name") // simple member function
}

// =========================
// 2. Primary Constructor + init block
// =========================
// Kotlin allows declaring a "primary constructor" directly in the class header.
// It is concise and good for classes whose main purpose is to hold state.
// The 'init' block is used for additional initialization logic.
class User(val name: String, var age: Int) {
    init {
        println("User created: $name, age: $age")
    }
}

// =========================
// 3. Secondary Constructor
// =========================
// Why does Kotlin have both primary and secondary constructors?
// - Primary constructor: concise, defines essential properties upfront.
// - Secondary constructor: allows flexibility and multiple ways of constructing the same class.
// Useful for backward compatibility or alternative initialization logic.
class Student {
    var name: String
    var grade: Int

    constructor(name: String, grade: Int) {  // secondary constructor
        this.name = name
        this.grade = grade
    }
}

// =========================
// 4. Data Class
// =========================
// Data classes are special: they automatically generate
// equals(), hashCode(), toString(), copy(), and componentN() for destructuring.
data class Book(val title: String, val price: Double)

// =========================
// 5. Inheritance
// =========================
// By default, Kotlin classes are 'final' (cannot be inherited).
// We must mark them 'open' to allow inheritance.
open class Animal {
    open fun sound() = println("Some sound")
}

class Dog : Animal() {
    override fun sound() = println("Woof!")  // explicit 'override' is required
}

// =========================
// 6. Interface
// =========================
// Interfaces can contain both abstract methods and methods with default implementation.
interface Drivable {
    fun drive()                     // abstract
    fun stop() = println("Stopped") // default implementation
}

class Car : Drivable {
    override fun drive() = println("Car is driving")
}

// =========================
// 7. Abstract Class
// =========================
// Abstract classes cannot be instantiated.
// They may contain abstract members (must be implemented) and concrete ones.
abstract class Shape {
    abstract fun area(): Double
    fun describe() = println("I am a shape") // concrete method
}

class Circle(val r: Double) : Shape() {
    override fun area() = Math.PI * r * r
}

// =========================
// (No need for main() here)
// The above code demonstrates: 
// - simple class declaration
// - primary vs secondary constructors
// - data classes
// - inheritance rules
// - interfaces
// - abstract classes
// =========================

lambda

// =========================
// Kotlin Lambda Expressions
// =========================

// 1. Basic Lambda Expression
// A lambda is an anonymous function (function without a name).
// Syntax: { parameter(s) -> body }
val square = { x: Int -> x * x }
// Usage: square(5)  -> 25

// 2. Lambda with multiple parameters
val add = { a: Int, b: Int -> a + b }
// Usage: add(2, 3) -> 5

// 3. Type inference
// If the context provides enough type information, you can omit parameter types.
val multiply: (Int, Int) -> Int = { a, b -> a * b }

// 4. Single parameter shortcut ('it')
// If there is only one parameter, you can omit its name and use 'it'.
val doubled = { x: Int -> x * 2 }
val doubled2: (Int) -> Int = { it * 2 }

// 5. Lambda as function argument
// Many Kotlin library functions (map, filter, forEach) take lambdas as arguments.
val numbers = listOf(1, 2, 3, 4)
val squares = numbers.map { it * it }   // [1, 4, 9, 16]
val evens = numbers.filter { it % 2 == 0 } // [2, 4]

// 6. Lambda with 'return'
// 'return' inside a lambda returns from the nearest function that takes the lambda.
// Often replaced with functions like 'forEach' or 'map' to avoid explicit loops.
fun process(nums: List<Int>) {
    nums.forEach {
        if (it < 0) return  // exits the entire process() function, not just the lambda
        println(it)
    }
}

// 7. Higher-order function
// A function that takes a lambda (function) as a parameter.
fun operateOnTwoNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// Example usage:
// operateOnTwoNumbers(3, 4, { x, y -> x + y })   // 7
// With Kotlin's lambda syntax sugar, we can write:
// operateOnTwoNumbers(3, 4) { x, y -> x + y }    // cleaner

// 8. Trailing Lambda Syntax
// If the last parameter of a function is a lambda, it can be placed outside the parentheses.
val result = numbers.fold(0) { acc, n -> acc + n }  // sum of list

https://play.kotlinlang.org

Views: 10

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.