Kotlin, use operator overloading BUT use it carefully
“With great power comes great responsibility”
Uncle Ben, Spider-Man
Kotlin is great and expressive language. One feature that CAN greatly improve expressiveness and readability are operator overloading. Key thing here is CAN improve, you have to use it carefully and not go over the top. If you abuse it your code can be as unreadable as it can be. With that said let’s see what good implementation looks like.
Examples we will use to showcase this are:
1. Food ordering application. We will have Cart
, Article
and Topping
.
2. Simple state change.
First let’s give a bit of a theory about operators and operator overloading in Kotlin. You have fixed set of operators and you can’t create your own, you can just use existing ones. You do it like this operator fun OPERATOR() {}
and you follow operator signature but operator fun
is a must. Some operators are invoke
/()
, plus
/+
, plusAssign
/+=
, get
/[]
etc. You can read documentation to learn more.
Lets start with food ordering application. Structure would look like this:
Pardon my MutableList
usage. Using List
is much better and adding Article
would ideally return new Cart
object and you would update it with Kotlin data class
copy()
method. This is for the sake of simplicity.
Our first use case is adding Article
to Cart
. Most “primitive” version of this would look like this:
If we take a look at how operator overloading is used through Kotlin itself we will find MutableList
implementation of +=
/plusAssign
.
This is something we can look up to and create our own +=
. It would look like this:
This is readable right? You know what’s it doing, it’s intuitive. Simply put, great. There is another operator : +
. We will not use it for this because +
assumes that expression returns something val a = 5 + 6
. something
+
somethingElse
returns (should return) value. In our example it would be confusing, +=
updates object, +
returns value.
We will do the same thing for Article
and Topping
.
Now, you may be tempted to implement +=
for Cart
and Topping
. That is an example of operator overloading hurting your code and design. Why are we adding Topping
to Cart
? Where does that Topping
go? On what? It doesn’t make sense logically nor semantically. You can see that this is easy line to cross so be careful and RESPONSIBLE.
Other use case would be simple state change. Lets say we have scenario where we track is some part of the UI expanded/collapsed and we want to toggle it with button. This can be visible/invisible etc. Whats important with this example is that it has TWO possible values, like true
or false
.
That state could look like this:
When we click that button state should change? If it was Collapsed
it should be Expanded
and vice versa. We can do that with if
checks but it’s again more primitive version:
Let’s look at something we all already know and use every day. !
.
This looks much better!
I will end this post here in order to keep it reasonably long. You can reach out to me if you have some better example, need help etc.
I will encourage you to explore other operators, especially invoke()
, in
, get
, set
could be useful.
You can find full code here.