Operator Overloading Workbook


Practice problems for Operator Overloading, Kept on a Leash. Each takes a minute or two. Write your own answer first, then click Show answer — nothing here is a trick question, just direct practice of the syntax from the lesson.

arithmetic and indexing

1. Add two vectors

Give data class Vec(val x: Int, val y: Int) a + operator that adds component-wise.

Show answer Hide answer
data class Vec(val x: Int, val y: Int) {
    operator fun plus(other: Vec) = Vec(x + other.x, y + other.y)
}

Vec(1, 2) + Vec(3, 4)   // Vec(4, 6)

a + b compiles to a.plus(b).

2. Index into a grid

Give Grid a get(x, y) so grid[x, y] reads a cell.

Show answer Hide answer
class Grid(private val cells: IntArray, val width: Int) {
    operator fun get(x: Int, y: Int) = cells[y * width + x]
}

3. Index assignment

Add a set(x, y, value) so grid[x, y] = 9 writes a cell.

Show answer Hide answer
operator fun set(x: Int, y: Int, value: Int) {
    cells[y * width + x] = value
}

4. Call an object

Give Adder(val by: Int) an invoke(x) so add5(10) works like a function call.

Show answer Hide answer
class Adder(val by: Int) {
    operator fun invoke(x: Int) = x + by
}

val add5 = Adder(5)
add5(10)   // 15

membership, comparison, assignment

5. Support the in keyword

Give Rectangle a contains(p: Point) so p in rect works.

Show answer Hide answer
operator fun Rectangle.contains(p: Point): Boolean = /* inside test */

p in rect compiles to rect.contains(p).

6. Comparison operators

Make Money(val cents: Int) support < and > by implementing Comparable.

Show answer Hide answer
data class Money(val cents: Int) : Comparable<Money> {
    override fun compareTo(other: Money) = cents.compareTo(other.cents)
}

compareTo backs <, >, <=, >=.

7. Mutate in place with +=

Give IntBag a plusAssign operator so bag += 3 adds an element to it in place.

Show answer Hide answer
class IntBag(private val items: MutableList<Int> = mutableListOf()) {
    operator fun plusAssign(x: Int) { items.add(x) }
}

+= calls plusAssign when it’s defined; otherwise it falls back to a = a + b via plus.

unary and iteration

8. Negate

Give Cents(val n: Int) a unary minus so -cents works.

Show answer Hide answer
data class Cents(val n: Int) {
    operator fun unaryMinus() = Cents(-n)
}

9. Make it for-loopable

Give Tree(private val nodes: List<String>) an iterator() so it works in a for loop.

Show answer Hide answer
class Tree(private val nodes: List<String>) {
    operator fun iterator() = nodes.iterator()
}

for (node in Tree(listOf("a", "b"))) println(node)

10. Scale by an Int

Give Money(val cents: Int) a times operator so Money(100) * 3 returns Money(300).

Show answer Hide answer
data class Money(val cents: Int) {
    operator fun times(n: Int) = Money(cents * n)
}

Money(100) * 3   // Money(300)

* maps to times — a good fit only because scaling money by a count has an obvious meaning.


Back to the lesson, Operator Overloading, Kept on a Leash, or on to the next one: coroutines.