Kotlin
2026-08-21 09:00
Unit 2: in tested membership and drove for loops.
Unit 3: 1 to "one" was a function, not syntax.
They are the same thing.
Certain language constructs are defined as calls to functions
with specific names.
Define such a function on your type, and the syntax works for it.
plus and plusAssign.equals and compareTo.get, set, contains, rangeTo, iterator.componentN.Java: to be iterable, implement Iterable.
Kotlin: define a function named iterator.
Which can be an extension — so a class you do not own becomes iterable.
Java — operators on built-in types only.
Scala — arbitrary new operators, and libraries nobody can read.
Kotlin — a fixed set of operators, and you decide what each means.
It prevents a function that happens to be named plus
from accidentally gaining operator syntax.
And it tells a reader that operator use is intended.
Note: p * 1.5 works. 1.5 * p does not, unless you define that too.
unaryPlus · unaryMinus · not · inc · dec
Arguably more readable, and no precedence surprises.
plus — new object, reassign. Requires a var.
plusAssign — modify in place, return Unit. Works on a val.
With both, += is ambiguous and the compiler reports an error.
Read-only collections define plus — a new collection.
Mutable ones define plusAssign — modified in place.
Which operator is available tells you which kind you have.
So it compares contents. Reference comparison is ===.
The opposite of Java, and the better way round —
content comparison is what you want, so it gets the shorter syntax.
In Java, a.equals(b) throws when a is null.
Which is why defensive Java puts the constant first.
equals is marked override, not operator — it is already marked in Any.
And it cannot be an extension: the inherited member would always win.
Unit 3’s dispatch rule, showing its consequences.
Plus sorting, max and min from the standard library.
The field-by-field version is faster than compareValuesBy.
Write the readable form. Optimise if a profiler says to.
A map’s get takes a key. Yours can take whatever suits.
Multiple parameters too: matrix[row, col].
Any Comparable gets one free — so compareTo already earned you this.
LocalDate is a JDK class. That extension makes it loop-able.
for (c in "abc") — CharSequence has an iterator extension.
c in 'a'..'z' — .. built a range, in called its contains.
One keyword, two functions.
Java ties this to implementing interfaces.
You cannot make somebody else’s class implement your interface.
Kotlin can give a library class indexing, iteration and ranges without touching it.
One more item on the data list, alongside equals, hashCode, toString, copy.
A real improvement on an out-parameter or an array.
Which is what map iteration was doing all along.
Map.Entry has component1 and component2 extensions.
Destructuring is positional, not by name.
Reorder a data class’s constructor and every destructuring silently changes meaning.
Still compiles. Values now wrong.
A property does not have to store its value in a field.
With by, its accessors are someone else’s job.
Runs on first access. Result cached.
Thread-safe by default.
No nullable field, no !!.
The notification logic exists in exactly one place.
A third observable property is one line.
class ObservableProperty(var propValue: Int, ...) {
operator fun getValue(p: Person, prop: KProperty<*>): Int = propValue
operator fun setValue(p: Person, prop: KProperty<*>, newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
}It lets a delegate behave differently per property.
By using the property’s name as a key.
Which is what the map-backed case relies on entirely.
A hidden field holding the delegate.
A getter calling getValue. A setter calling setValue.
Any delegate you meet, however clever, is doing only this.
Fixed and dynamic attributes, accessed identically.
The class reads like a plain object. The delegate does the database work.
== calls equals and checks null first, which removes a Java bug class.in was two functions; to was an infix extension.Higher-Order Functions returns to the functional thread.
Unit 5 taught you to use lambdas.
This one is about writing functions that take and return them — and inline.
Kotlin · Operator Overloading and Other Conventions