Language Elements

Data Types

Kotlin Classes

Kotlin Operators

Kotlin Constructors

Kotlin Null Safety

Extension Functions

Lambda Functions

Object Oriented Kotlin

Data Classes

Coroutines

Kotlin Collections

Kotlin Data Structures

Kotlin Algorithms

Delegation

Lateinit and Lazy Initialization

Kotlin Scope Functions

Kotlin Key Words

Kotlin Example Codes

Kotlin Interview Questions

In object-oriented programming with Kotlin, a class groups related data (properties) and behavior (functions/methods) into one reusable unit. Classes act as blueprints from which we create objects (also called instances). Each object has its own copy of instance data (properties defined in the class body), while class-level data (e.g., in companion object or top-level properties) can be shared across instances. Behavior is shared by default and can be customized or extended in many ways — most commonly through inheritance and overriding, but also through composition, delegation (using by), interface default implementations, extension functions, and properties.

Besides using classes very similar to Java, Kotlin introduces several modern class kinds that provide new capabilities not easily achievable in classic OOP, while also reducing boilerplate in many common cases. These new kinds do not merely reduce code — they add expressive power, stronger type safety, performance benefits, and enable patterns that are difficult or impossible with traditional Java classes.

Kotlin Class Types

1. Regular Class


class Person(val name: String, var age: Int) {
    fun greet() = println("Hello, I'm $name and $age years old")
}

val alice = Person("Alice", 30)
alice.greet()           // Hello, I'm Alice and 30 years old

2. Data Class

Automatically provides useful methods — no boilerplate needed.


data class User(val id: Int, val name: String)

val user1 = User(1, "Bob")
val user2 = user1.copy(name = "Bobby")

println(user1)                    // User(id=1, name=Bob)
println(user1 == User(1, "Bob"))  // true (structural equality)
println(user2)                    // User(id=1, name=Bobby)

3. Enum Class


enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

val dir = Direction.EAST
println(dir)    // EAST

4. Sealed Class

Restricted hierarchy — all subclasses must be defined in the same file.


sealed class Result
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
object Loading : Result()

fun handle(result: Result) = when (result) {
    is Success -> println("Success: ${result.data}")
    is Error   -> println("Error: ${result.message}")
    Loading    -> println("Loading...")
    // No 'else' needed — compiler knows all cases
}

5. Abstract Class


abstract class Animal {
    abstract fun sound()
    fun sleep() = println("Zzz...")
}

class Dog : Animal() {
    override fun sound() = println("Woof!")
}

val dog = Dog()
dog.sound()   // Woof!
dog.sleep()   // Zzz...

6. Interface


interface Printable {
    fun print()                   // abstract
    fun preview() = println("Previewing...")  // default implementation
}

class Document : Printable {
    override fun print() = println("Printing document")
}

val doc = Document()
doc.print()     // Printing document
doc.preview()   // Previewing...

7. Object Declaration (Singleton)


object Logger {
    fun info(msg: String) = println("INFO: $msg")
    fun error(msg: String) = println("ERROR: $msg")
}

// Used directly — no instance needed
Logger.info("App started")

8. Nested vs Inner Class


class Outer {
    private val secret = "I'm hidden"

    class Nested {                     // static-like
        fun hello() = "Hello from nested"
    }

    inner class Inner {                // holds reference to Outer
        fun reveal() = secret
    }
}

println(Outer.Nested().hello())        // Hello from nested
val outer = Outer()
println(outer.Inner().reveal())        // I'm hidden

9. Inline (Value) Class

Wraps a single value with zero runtime overhead — perfect for type-safe IDs, units, etc.


@JvmInline
value class UserId(val value: Int)

fun process(id: UserId) = println("Processing user ${id.value}")

val uid = UserId(123)
process(uid)          // Processing user 123
// At runtime: just an Int — no extra object created



Copyright © by Zafar Yasin. All rights reserved.