KtKotlin · Lesson 4 of 8

Classes & Data Classes

A Java class with getters, setters, equals, hashCode, and toString is ~50 lines. The Kotlin data class equivalent is one. This lesson is why people switch.

Kotlin
// Constructor is in the header; val/var make properties:
class Student(val name: String, var grade: Int = 0) {
    fun praise() = "$name is doing great!"
}

fun main() {
    val ada = Student("Ada", 95)
    println(ada.name)        // property access, no getters
    ada.grade = 97           // var property is settable
    println(ada.praise())
}

// data class: equals, hashCode, toString, copy — free:
data class Point(val x: Int, val y: Int)

fun main2() {
    val p1 = Point(1, 2)
    val p2 = Point(1, 2)
    println(p1 == p2)             // true (structural equality)
    println(p1)                   // Point(x=1, y=2)
    val p3 = p1.copy(y = 5)       // Point(x=1, y=5)
    val (x, y) = p3               // destructuring
}
Kotlin
// Inheritance — classes are final unless marked 'open':
open class Shape(val name: String) {
    open fun area(): Double = 0.0
}

class Circle(private val radius: Double) : Shape("circle") {
    override fun area() = Math.PI * radius * radius
}

// Interfaces:
interface Drawable {
    fun draw()
    fun describe() = "a drawable thing"   // default implementation
}

// Sealed classes — a closed set of subtypes; when() knows them all:
sealed class Result
data class Success(val data: String) : Result()
data class Failure(val error: String) : Result()

fun handle(r: Result) = when (r) {
    is Success -> "got: ${r.data}"
    is Failure -> "oops: ${r.error}"
    // no else needed — compiler knows these are all the cases
}

// object — a singleton in one keyword:
object Config {
    val version = "1.0"
}
◆ Note
Sealed classes + when is Kotlin's answer to Rust enums / TypeScript discriminated unions: model 'a value that is one of N shapes' and the compiler guarantees every shape is handled. Android code uses this pattern for UI state constantly.