Operator Overloading and Other Conventions

Keywords

ver. 1.0.0

How Kotlin maps familiar syntax to named conventions you can implement — operators, indexing, destructuring and property delegates

This unit explains Kotlin conventions: syntactic operators and constructs are translated to calls to specially named functions you can implement on your types. You learn to overload arithmetic and unary operators with operator functions (and the plus vs plusAssign compound-assignment rule), make == and ordering use equals and compareTo, provide get/set/contains/rangeTo/iterator so your types support indexing, membership, ranges and for loops, enable destructuring via componentN functions (and how data classes supply them), and delegate property access with by by supplying getValue/setValue (including standard delegates and storing properties in maps). By the end you can endow your types with arithmetic, comparison, indexing, iteration, destructuring and delegated behavior.

Kotlin conventions connect language syntax to plain functions and methods that you (or libraries) can define on your types. Rather than seeing operators and special forms as intrinsic syntax, the language routes them to functions with fixed names and signatures; implementing those functions gives your types the same expressive capabilities the language uses for built-ins.

You will learn how to: - Overload arithmetic and unary operators by declaring operator functions like plus, minus, times, div, rem and unary variants, so +, -, *, /, % and unary +/- work on your types. Understand the subtlety with compound assignment: x += y can translate to either plusAssign if present or to x = x.plus(y) otherwise, so define the appropriate one but avoid defining both inconsistently. - Make equality and ordering behave idiomatically by implementing equals (which Kotlin wires to == with a safe null check) and compareTo (which provides <, >, <=, >= when your type implements Comparable). The built-in null check on == eliminates a common Java pitfall. - Support indexing, membership testing, ranges and iteration by implementing get/set (for p[index] and p[index] = value), contains (for in checks), rangeTo (for .. ranges), and iterator (for for loops). These conventions explain why in earlier appeared to have two roles: membership and driving for loops are both backed by convention-based functions. - Enable destructuring declarations via component1(), component2(), …; data classes automatically generate these for primary-constructor properties, but you can provide them yourself for any type. - Delegate property access with by by providing a delegate object that implements getValue and setValue. Learn standard delegates like lazy and Delegates.observable, the compiler translation rule for property delegation, and the common pattern of storing property values in a map (used by frameworks to back dynamic or reflective properties).

After this unit you will be able to give your own types arithmetic, comparison, indexing, iteration, destructuring and delegated-property behaviour by implementing the appropriate convention functions, and you will recognize patterns used by libraries and frameworks that rely on these conventions. The next topic builds on this foundation by treating functions as first-class values and exploring higher-order functions and inline to reduce their cost.

Materials

Source document

  • Kotlin in Action, Second Edition, Sebastian Aigner, Roman Elizarov, Svetlana Isakova, and Dmitry Jemerov, Manning, April 2024 — Link — Page 197-226