Classes and Objects
Declaring classes, constructors, and properties — and how Kotlin collapses fields, getters, and setters into one concept.
2 min de lectura
A class in Kotlin bundles data (properties) and behavior (functions) together, same as in most object-oriented languages — but Kotlin's syntax is noticeably more compact than Java's.
A basic class
class User(val name: String, var age: Int) {
fun hasBirthday() {
age += 1
println("$name is now $age")
}
}
val user = User("Alice", 29)
println(user.name) // Alice
user.hasBirthday() // Alice is now 30That parameter list right after the class name is the primary constructor. Declaring a constructor parameter with val or var does two things at once: it accepts the value in the constructor, and declares it as a property of the class. There's no separate field declaration, no assignment inside a constructor body, and no hand-written getter — user.name and user.age just work.
Comparing to the equivalent without shorthand
To appreciate what that constructor shorthand is doing, here's roughly what it saves you from writing by hand:
class User(name: String, age: Int) {
val name: String
var age: Int
init {
this.name = name
this.age = age
}
}Both versions behave identically. Kotlin just doesn't make you write the second one.
init blocks
An init block runs as part of construction, useful for validation or setup logic beyond simple assignment:
class User(val name: String, var age: Int) {
init {
require(age >= 0) { "Age cannot be negative" }
}
}
User("Alice", -5) // throws IllegalArgumentException: Age cannot be negativeCustom getters and setters
Properties can define their own logic instead of just storing a value directly:
class Rectangle(val width: Double, val height: Double) {
val area: Double
get() = width * height
}
val rect = Rectangle(4.0, 5.0)
println(rect.area) // 20.0 — recalculated every time it's readarea isn't stored — it's computed fresh on every access, but callers use rect.area exactly like a stored property, with no () needed.
Secondary constructors
Most classes only need the primary constructor, but a class can define additional ones with constructor, each ultimately delegating to the primary:
class User(val name: String, var age: Int) {
constructor(name: String) : this(name, age = 0)
}
val newUser = User("Bob") // age defaults to 0 via the secondary constructorIn practice, a default argument (var age: Int = 0) usually replaces the need for a secondary constructor entirely — reach for secondary constructors mainly when interoperating with Java frameworks that expect them.
Plain classes like User are the general-purpose tool. The next lesson covers data class — a specialized declaration for classes that primarily hold values, and one of Kotlin's most-used features.