Operator overloading

Operator overloading - About the author

===

11 Operator overloading

Kotlin has a fixed number of symbolic operators we can easily use on any class. The way is to create a function with a reserved name that will be mapped to the symbol. Overloading these operators will increment code readability and simplicity.

In order to alert the compiler we want to overload an operator, functions must be annotated with the operator modifier

11.1 Operators tables

Here you can see a set of tables that include an operator and its corresponding function. A function with that name must be implemented to enable the possibility of using the operator in a specific class.

Unary operations

+a

a.unaryPlus()

-a

a.unaryMinus()

!a

a.not()

a++

a.inc()

a–

a.dec()

Binary operations

11 Operator overloading

49 a+b

a.plus(b)

a-b

a.minus(b)

a*b

a.times(b)

a/b

a.div(b)

a%b

a.mod(b)

a..b

a.rangeTo(b)

a in b

b.contains(a)

a !in b

!b.contains(a)

a += b

a.plusAssign(b)

a -= b

a.minusAssign(b)

a *= b

a.timesAssign(b)

a /= b

a.divAssign(b)

a %= b

a.modAssign(b)

Array-like operations

a[i]

a.get(i)

a[i, j]

a.get(i, j)

a[i_1, …, i_n]

a.get(i_1, …, i_n)

a[i] = b

a.set(i, b)

a[i, j] = b

a.set(i, j, b)

a[i_1, …, i_n] = b

a.set(i_1, …, i_n, b)

Equals operation

a == b

a?.equals(b) ?: b === null

a != b

!(a?.equals(b) ?: b === null)

The equals operations are a bit different, because they use a more complex trans- lation in order to make a proper equals checking, and because they expect an exact function specification, and not just a specific name. The function must be implemented exactly like this:

1 operator fun equals (other: Any?): Boolean

Operators === and !== do identity checks (they are == and != in Java respectively) and can’t be overloaded.

11 Operator overloading

Function invocation

a(i)

a.invoke(i)

a(i, j)

a.invoke(i, j)

a(i_1, …, i_n)

a.invoke(i_1, …, i_n)

11.2 An example

As you can imagine, Kotlin lists have the array-like operations implemented in the standard library, so we can get list items the same way we’d do in Java arrays. But it goes beyond: in mutable lists, the item can also be set directly in a very simple way:

1 val x = myList[ 2 ] 2 myList[ 2 ]= 4

If you remember, we have a data class called ForecastList , which basically consists of a list with some extra info. It’d be interesting to access its items directly instead of having to request its internal list to get an item. On a totally unrelated note, I’m also going to implement a size property, which will simplify the current adapter a little more:

1 data class ForecastList ( val city: String, val country: String, 2 val dailyForecast: List<Forecast>) {

4 val size: Int 5 get () = dailyForecast.size

7 operator fun get (position: Int): Forecast = dailyForecast[position] 8 }

It makes our onBindViewHolder a bit simpler:

11 Operator overloading

1 override fun onBindViewHolder (holder: ViewHolder, position: Int) { 2 with(weekForecast[position]) { 3 holder.textView.text = "$date - $description - $high/$low" 4 } 5 }

As well as the getItemCount() function:

1 override fun getItemCount (): Int = weekForecast.size

11.3 Operators in extension functions

We don’t need to stick to our own classes, but we could even extend existing classes using extension functions to provide new operations to third party libraries. For instance, we could access to ViewGroup views the same way we do with lists:

1 operator fun ViewGroup . get (position: Int): View 2 = getChildAt(position)

Now it’s really simple to get a view from a ViewGroup by its position:

1 val container: ViewGroup = find(R.id.container)

2 val view = container[ 2 ]

Take a look at the branch for this chapter²⁴ , and then you can go on with the next one.

²⁴ https://github.com/antoniolg/Kotlin-for-Android-Developers/tree/chapter-11