Classes are fundamental building blocks in object-oriented programming, used to encapsulate data (fields or properties) and behavior (methods or functions). Kotlin, like Java, C++, and other object-oriented languages, relies on classes to define reusable blueprints from which objects (instances) are created.
Kotlin supports traditional Java-style classes, but it also introduces several new types of classes and enhancements to reduce boilerplate code and make definitions more expressive and concise. Many common Java classes and patterns have direct Kotlin equivalents, but Kotlin's design philosophy leads to more idiomatic and compact structures.
Types of Classes in Kotlin
Kotlin offers a variety of class types, each serving a specific purpose:
- Regular classes
- Data classes
- Enum classes
- Sealed classes
- Abstract classes
- Interface (functional type-like) classes
- Object declarations (singleton classes)
- Inner and nested classes
- Inline classes (value classes)
1. Regular Class
A typical class that contains properties and methods.
class Person(val name: String, var age: Int) {
fun greet() {
println("Hello, my name is $name.")
}
}
val p = Person("Alice", 30)
p.greet()
2. Data Class
Used to hold data. Automatically provides equals(), hashCode(), toString(), etc.
data class User(val id: Int, val name: String)
val user = User(1, "Bob")
println(user)
3. Enum Class
Represents a fixed set of constants.
enum class Direction {
NORTH, SOUTH, EAST, WEST
}
val dir = Direction.EAST
println(dir)
4. Sealed Class
Restricts class hierarchy to a known set of subclasses. Often used for representing restricted state models and
when using when expressions.
sealed class Result
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
fun handle(result: Result) {
when (result) {
is Success -> println("Success: ${result.data}")
is Error -> println("Error: ${result.message}")
}
}
5. Abstract Class
Cannot be instantiated directly. Must be subclassed. May contain abstract methods.
abstract class Animal {
abstract fun sound()
}
class Dog : Animal() {
override fun sound() = println("Bark!")
}
val d = Dog()
d.sound()
6. Interface
Defines a contract of methods that implementing classes must fulfill.
interface Clickable {
fun click()
}
class Button : Clickable {
override fun click() = println("Button clicked")
}
7. Object Declaration (Singleton)
Defines a single instance of a class.
object Logger {
fun log(msg: String) {
println("LOG: $msg")
}
}
Logger.log("Started application")
8. Nested and Inner Classes
Nested classes are static by default. Inner classes hold a reference to the outer class.
class Outer {
private val secret = "Secret"
class Nested {
fun hello() = "Hello from nested"
}
inner class Inner {
fun reveal() = "Revealing: $secret"
}
}
9. Value (Inline) Classes
Wraps a single value to avoid object overhead. Used for type-safety with no runtime cost.
@JvmInline
value class UserId(val id: Int)
fun greet(userId: UserId) {
println("User ID is ${userId.id}")
}
When to Use Each Class Type
- Regular class: For general-purpose objects with state and behavior.
- Data class: For models and DTOs that hold data only.
- Enum class: For fixed constant values (e.g., directions, states).
- Sealed class: For closed set of types in decision structures like
when. - Abstract class: When you want partial implementation with common logic.
- Interface: When you need to define behavior without state or multiple inheritance.
- Object: For stateless utility or singleton classes.
- Nested/Inner class: For grouping logic tightly related to an outer class.
- Value class: For lightweight wrappers around primitive or single values.
Kotlin's class system is rich and flexible, blending traditional object-oriented concepts with modern, expressive constructs like data, sealed, and object classes. By choosing the right class type, developers can write cleaner, more readable, and performant code that clearly expresses intent.