Fred
Fred

Reputation: 17085

Any way to achieve something like overriding an operator in kotlin?

Recently I was working with lists in kotlin and had the following snippet:

a = listOf(1, 2, 3, 4)
println(a[-2])

Of course this causes an IndexOutOfBoundsException so I thought it would be nice to extend this functionality. So I thought one could override the get operator in the List class:

operator fun <T> List<T>.get(index: Int): T =
        // Here this should call the non-overridden version of
        // get. 
        get(index % size)

I understand that extensions are just static methods and therefore cannot be overridden, but is there a way one can achieve something like this?

Of course you could just create another function

fun <T> List<T>.safeGet(index: Int): T = get(index % size)

but I'd like to know if there are other ways.

(I understand that index % size is a very naive way of doing what I want, but it's not the focus of my question and makes the code smaller.)

EDIT

When I wrote this question I thought the % operator would return always positive numbers when the right hand side is positive - like in python. I'm keeping the original question here just for consistency.

Upvotes: 2

Views: 180

Answers (2)

Naetmul
Naetmul

Reputation: 15552

Since get operator is already defined in List, you cannot redefine get (with one Int parameter). However, you can override invoke operator, which is not defined in List.

fun main(args: Array<String>) {
    val a = listOf(1, 2, 3, 4)
    println(a(-2))
}

// If `index` is negative, `index % size` will be non-positive by the definition of `rem` operator.
operator fun <T> List<T>.invoke(index: Int): T = if (index >= 0) get(index % size) else get((-index) % (-size))

although I think that creating a new extension method to List with an appropriate name will be more preferable option.

As a sidenote, (positive value) % (negative value) is non-negative, and (negative value) % (positive value) is non-positive.
% in Kotlin corresponds to rem in Haskell in the following example: https://stackoverflow.com/a/28027235/869330

Upvotes: 3

ice1000
ice1000

Reputation: 6569

You're trying something impossible, because extensions are always shadowed by members, even @JvmName cannot save you.

Workaround: use your second solution, or add a Unit parameter which is ugly (looks like a[x, Unit]) but can exist with its own get method together.

Another solution: create your own List implementation (recommended).

Upvotes: 2

Related Questions