How do comparison operators (`<`, `>=`), `in`, and `..` work through operator conventions? Explain `compareTo`, `contains`, and `rangeTo`.
answer
- One compareTo Int drives <, <=, >, >=
- Comparable gives compareTo for free
- a in c -> c.contains(a) (container is receiver)
- a..b -> rangeTo; a..<b -> rangeUntil
- == uses equals, not an operator fun
basics
~10 sAll comparison operators (<, <=, >, >=) use one compareTo function returning an Int. a in b calls b.contains(a). a..b calls a.rangeTo(b) to make a range.
solid answer
~40 sA single `operator fun compareTo(other): Int` powers `<`, `<=`, `>`, and `>=`: the compiler rewrites `a < b` to `a.compareTo(b) < 0`, `a >= b` to `a.compareTo(b) >= 0`, and so on. `compareTo` must return `Int` (negative/zero/positive). Implementing `Comparable<T>` gives you this operator automatically since its `compareTo` is already `operator`. The `in` operator maps to `contains`: `a in c` -> `c.contains(a)`, and `a !in c` -> `!c.contains(a)`; `contains` must return `Boolean`. The range operator `..` maps to `rangeTo`: `a..b` -> `a.rangeTo(b)`. There's also `..<` mapping to `rangeUntil` for half-open ranges (Kotlin 1.9+). Equality (`==`) is special — it goes through `equals`, not an `operator` function.
code
kotlin · 9 linesdata class Temp(val celsius: Int) : Comparable<Temp> {
override fun compareTo(other: Temp) = celsius.compareTo(other.celsius)
operator fun rangeTo(other: Temp) = TempRange(this, other)
}
class TempRange(val start: Temp, val end: Temp) {
operator fun contains(t: Temp) = t >= start && t <= end
}
Temp(20) in Temp(0)..Temp(30) // true: rangeTo builds range, contains checks, < uses compareTogo deeper
Knows < uses compareTo and in uses contains at a high level.
States compareTo returns Int and drives all four ordering ops, and that contains' receiver is the container.
Distinguishes Comparable-provided operator vs custom contains/rangeTo, knows ..</rangeUntil and that == uses equals not an operator fun.
Designs range/comparable value types coherently so in, .., and ordering compose, and guards against inconsistent compareTo/equals contracts.
## Comparison: one function for four operators Kotlin routes **all four** ordering operators through a single function: ``` a < b -> a.compareTo(b) < 0 a > b -> a.compareTo(b) > 0 a <= b -> a.compareTo(b) <= 0 a >= b -> a.compareTo(b) >= 0 ``` Rules for `compareTo`: - Must be declared `operator` and **return `Int`** (negative if `a < b`, `0` if equal-ordering, positive if `a > b`). - If your type implements `Comparable<T>`, you get this for free: `Comparable.compareTo` is already declared `operator`, so `<`/`>` work without extra code. ```kotlin class Version(val major: Int, val minor: Int) : Comparable<Version> { override fun compareTo(other: Version): Int = compareValuesBy(this, other, Version::major, Version::minor) } Version(1, 2) < Version(1, 5) // compareTo(...) < 0 -> true ``` ## Membership: `in` and `contains` ``` a in c -> c.contains(a) a !in c -> !c.contains(a) ``` - `contains` must be declared `operator` and **return `Boolean`**. - The receiver of `contains` is the **right** operand (the container), which is the reverse of the source order. ```kotlin class IntRangeSet(val from: Int, val to: Int) { operator fun contains(value: Int): Boolean = value in from..to } 5 in IntRangeSet(1, 10) // IntRangeSet(1,10).contains(5) -> true ``` ## Ranges: `..` and `..<` ``` a..b -> a.rangeTo(b) a..<b -> a.rangeUntil(b) // half-open, Kotlin 1.9+ ``` The standard library defines `rangeTo` on the primitive numeric/char/comparable types, producing `IntRange`, `CharRange`, etc. You can define `rangeTo` on your own type to build custom range objects — often combined with `contains` so `x in a..b` works. ## What is NOT an operator function - **`==` / `!=`** route through **`equals`** (with a built-in null check), not an `operator fun`. You override `equals`, you don't mark it `operator`. - **`===` / `!==`** (referential identity) cannot be overloaded at all. ## Why it matters Implementing `Comparable` + `contains` + `rangeTo` lets value types read naturally: `if (v in minVer..maxVer)` works because `in` -> `contains` and `..` -> `rangeTo` cooperate.
- Why does implementing `Comparable<T>` immediately enable `<` and `>`?Because `Comparable.compareTo` is already declared `operator`, so the compiler can desugar the ordering operators to it.
- Which operand is the receiver of `contains` in `a in c`?The container `c` (the right operand): it's `c.contains(a)`.
saying these in an interview costs you the question
- Trying to overload `==` with an `operator fun equals`
- Making `compareTo` return Boolean instead of Int
- Thinking each of `<`, `>`, `<=`, `>=` needs its own function
- Getting the `contains` receiver backwards (a.contains(c))