Reputation: 17085
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
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
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