Learning Kotlin: Operators

Submitted by Robert MacLean on Sun, 07/29/2018 - 18:13

More Information

  • This is the 17th post in a multipart series.
    If you want to read more, see our series index

This next post is an introduction to operators in Kotlin, not the basic the "use a plus sign to add numbers together" stuff (you read this blog, you got to be smart enough to figure that out). No, this post is about just how amazingly extensive the language is when it comes to support for allowing your classes to use them.

Adding things together

So let's start with a simple addition things together with plus I said we wouldn't do. In the following example code, we have a way to keep track of scoring events in a rugby game and I would like to add up those events to get the total score:

  1. enum class scoreType {
  2.     `try`,
  3.     conversion,
  4.     kick
  5. }
  6.  
  7. data class score(val type:scoreType) {
  8.     fun points() = when(this.type) {
  9.         scoreType.`try` -> 5
  10.         scoreType.conversion -> 2
  11.         scoreType.kick -> 3
  12.     }
  13. }
  14.  
  15. fun main(args: Array<String>) {
  16.     val gameData = listOf(score(scoreType.`try`), score(scoreType.conversion), score(scoreType.`try`), score(scoreType.kick))
  17.     var totalPoints = 0
  18.     for (event in gameData) {
  19.         totalPoints = event + totalPoints
  20.     }
  21.  
  22.     println(totalPoints)
  23. }

This obviously won't compile, you can't += an Int and my own class? Right?!

We could make this change, which is probably the better way but for my silly example, let us say this isn't ideal.

  1.         totalPoints = event.points() + totalPoints

So to get our code to compile we just need a function named plus which has the operator keyword and whle I could call this myself, the Kotlin compiler is smart enough to now make it just work:

  1. data class score(val type:scoreType) {
  2.     fun points() = when(this.type) {
  3.         scoreType.`try` -> 5
  4.         scoreType.conversion -> 2
  5.         scoreType.kick -> 3
  6.     }
  7.  
  8.     operator fun plus(other:Int) = this.points() + other
  9. }

How cool is that?!

If I wanted to take it further and support say totalPoints += event then you would need to add a function to Integer which tells it how to add a score to it. Thankfully that is easy with extension functions:

  1. operator fun Int.plus(other:score) = this + other.points()

Extensive

While the above is a bit silly, imagine building classes for distances, time, weights etc... being able to have a kilogram and a pound class and add them together! What makes Kotlin shine is how extensive it is, just look at this list!

Class Operators Method Example Expression
Arithmetic +, '+=' plus first + second
Augmented Assignments += plusAssign |first += second`
Unary + unaryPlus +first
Increment & Decrement ++ inc first++
Arithmetic -, -= minus first - second
Augmented Assignments -= minusAssign first -= second
Unary - unaryMinus `-first
Increment & Decrement -- dec first--
Arithmetic *, *= times first * second
Augmented Assignments *= timesAssign first *= second
Arithmetic /, /= div first / second
Augmented Assignments /= divAssign first /= second
Arithmetic %, %= rem first % second
Augmented Assignments %= remAssign first %= second
Equality ==, != equals first == second
Comparison >, <, <=, >= compareTo first > second
Unary ! not !first
Arithmetic .. rangeTo first..second
In in, !in contains first in second
Index Access [, ] get This returns a value | first[index]
Index Access [, ] set This sets a value | first[index] = second
Invoke () invoke first()

I am going to go through some of these in more detail in future blog posts, but one I wanted to call out now:

Augmented Assignments vs. Plus or Minus

You might wonder why, when we just implemented plus above we got both support for + and += and the table lists += under both plus and augmented? Why both - because you may want to support just += without supporting +.