Skip to content
AgileLogics
6 min read

Classes and Objects

Prerequisites: Functions, Lambdas and higher-order functions

A class is a blueprint that describes a kind of thing: the data it holds (properties) and what it can do (methods — functions inside a class). An object is one actual thing built from that blueprint, also called an instance.

Real-world analogy: a class is a cookie cutter; objects are the cookies. One cutter, many cookies — each can have different icing, but they all share the same shape.

Syntax

Kotlin declares properties right in the class header, in the primary constructor:

class User(val name: String, var age: Int)

That one line declares a class with two properties and a constructor that sets them.

Example

class Dog(val name: String, val breed: String) {
    var tricks = 0

    fun bark() = "$name says woof!"

    fun learnTrick() {
        tricks++
    }

    fun describe() = "$name the $breed knows $tricks tricks"
}

fun main() {
    val rex = Dog("Rex", "beagle")
    val luna = Dog("Luna", "collie")

    println(rex.bark())
    rex.learnTrick()
    rex.learnTrick()
    println(rex.describe())
    println(luna.describe())
}

Expected output

Rex says woof!
Rex the beagle knows 2 tricks
Luna the collie knows 0 tricks

Line by line:

  • class Dog(val name: String, val breed: String) — val makes each constructor parameter a read-only property of every Dog.
  • var tricks = 0 — a property declared in the body, starting at 0.
  • bark, learnTrick, and describe are methods. Inside them, properties are used directly by name.
  • Dog("Rex", "beagle") creates an instance. There's no new keyword in Kotlin.
  • Each object has its own data: teaching Rex tricks doesn't affect Luna.

Properties are accessed with a dot: rex.name, rex.tricks. Because name is a val, rex.name = "Max" doesn't compile; tricks is a var, but only the class changes it here.

Common mistakes

  • Leaving out val or var in the constructor: class Dog(name: String) makes name a plain constructor parameter, not a property — rex.name then fails with Unresolved reference 'name'.
  • Printing an object of an ordinary class: println(rex) shows something like Dog@1b6d3586. Data classes (a later lesson) print their properties instead.

Practice

Create a BankAccount class with an owner and a balance that starts at 0.0, with deposit(amount) and summary() methods. summary() should return "Ada has 150.0" after depositing 100 and 50.

Show solution
class BankAccount(val owner: String) {
    var balance = 0.0

    fun deposit(amount: Double) {
        balance += amount
    }

    fun summary() = "$owner has $balance"
}

fun main() {
    val account = BankAccount("Ada")
    account.deposit(100.0)
    account.deposit(50.0)
    println(account.summary())
}
Ada has 150.0