A class bundles data and behavior together:

class Dog(val name: String, var age: Int) {
    fun bark() {
        println("$name says Woof!")
    }
}

val rex = Dog("Rex", 3)
rex.bark()          // Rex says Woof!
rex.age = 4         // age is a var, so it can change

Notice the constructor parameters are declared directly in the class header — no separate constructor method or field assignment needed.

Inheritance

Classes are final (cannot be subclassed) by default in Kotlin — you must explicitly mark a class open to allow inheritance:

open class Animal(val name: String) {
    open fun makeSound() {
        println("$name makes a sound")
    }
}

class Cat(name: String) : Animal(name) {
    override fun makeSound() {
        println("$name says Meow!")
    }
}

val animals: List<Animal> = listOf(Animal("Generic"), Cat("Whiskers"))
for (a in animals) {
    a.makeSound()   // Generic makes a sound / Whiskers says Meow!
}

This deliberate “closed by default” design avoids a common source of fragile-base-class bugs in other object-oriented languages.