Kotlin Classes

Classes are blueprints for objects, encapsulating state (properties) and behavior (methods). Kotlin simplifies class definitions with primary constructors, property declarations, and concise syntax.

1. Basic Class Declaration

Use class keyword. Without constructor parameters, define body in braces.

class Person {
  var name: String = ""
  var age: Int = 0
  fun greet() {
    println("Hello, \$name! You are \$age years old.")
  }
}
val p = Person()
p.name = "Alice"
p.age = 30
p.greet()

Output:
Hello, Alice! You are 30 years old.

2. Primary Constructor & Property Declaration

Declare constructor and properties inline.

class Person(val name: String, var age: Int) {
  fun info() = "Name: \$name, Age: \$age"
}
val p2 = Person("Bob", 25)
println(p2.info())

Output:
Name: Bob, Age: 25

3. init Block

Run initialization logic after primary constructor.

class Person(val name: String, var age: Int) {
  init {
    require(age >= 0) { "Age must be non-negative" }
    println("Created Person: \$name, \$age")
  }
}
val p3 = Person("Carol", 28)

Output:
Created Person: Carol, 28

4. Secondary Constructors

Define additional constructors using constructor, delegating to primary.

class Rectangle(val width: Int, val height: Int) {
  constructor(side: Int): this(side, side)
  fun area() = width * height
}
val sq = Rectangle(5)
println("Area: \${sq.area()}")

Output:
Area: 25

5. Visibility Modifiers

Control access: public (default), private, protected, internal.

class Secret {
  private val secretCode = 1234
  fun reveal() = secretCode
}
val s = Secret()
// println(s.secretCode) // Error: private
println(s.reveal())     // 1234

6. Inheritance and open

By default classes are final. Mark with open to allow subclassing.

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")
}
Dog("Rex").speak()

Output:
Rex barks

7. Abstract Classes & Interfaces

abstract classes may contain abstract members. interface defines contracts.

abstract class Shape {
  abstract fun area(): Double
}
class Circle(val r: Double): Shape() {
  override fun area() = Math.PI * r * r
}
interface Drivable {
  fun drive(): String
}
class Car: Drivable {
  override fun drive() = "Vroom!"
}
println(Circle(2.0).area())
println(Car().drive())

8. Data Classes

Automatically generate equals, hashCode, toString, copy, and destructuring.

data class User(val id: Int, val name: String)
val u1 = User(1, "Alice")
val u2 = u1.copy(name = "Bob")
println(u1)               // User(id=1, name=Alice)
val (id, nm) = u2
println("ID=\$id, Name=\$nm")

9. Sealed Classes

Restrict subclassing to nested types. Enable exhaustive when checks.

sealed class Result
data class Success(val data: String): Result()
data class Error(val err: Throwable): Result()
fun handle(r: Result) = when(r) {
  is Success -> "Got \${r.data}"
  is Error   -> "Error: \${r.err.message}"
}
println(handle(Success("OK")))
println(handle(Error(Exception("Fail"))))

10. Companion Objects

Define static-like members inside companion object.

class Util {
  companion object {
    const val VERSION = "1.0"
    fun info() = "Util v\$VERSION"
  }
}
println(Util.VERSION)
println(Util.info())

11. Nested vs Inner Classes

nested class has no reference to outer; inner carries this@Outer.

class Outer {
  private val x = 1
  class Nested {
    fun msg() = "Nested"
  }
  inner class Inner {
    fun msg() = "Inner x=\$x"
  }
}
println(Outer.Nested().msg())
println(Outer().Inner().msg())

12. Summary & Best Practices

- Kotlin favors concise class definitions with primary constructors.
- Use data classes for simple data holders.
- Mark classes open only when subclassing is needed.
- Prefer sealed classes for closed hierarchies.
- Keep initialization in init blocks and validate early.
- Use companion objects for factory methods and constants.
- Choose nested vs inner based on whether you need access to outer.
- Leverage interfaces for multiple inheritance of behavior.
- Document public API with KDoc for clarity.

Previous: Kotlin Strings | Next: Kotlin Properties and Fields

<
>