有什么方法可以实现像在kotlin中覆盖运算符的东西吗?

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

最近,我在Kotlin处理列表,并有以下片段:

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

当然,这会导致IndexOutOfBoundsException,所以我认为扩展这个功能会更好。所以我认为有人可以覆盖List类中的get操作符:

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

我理解扩展只是静态方法,因此不能被重写,但是有没有一种方法可以实现这样的事情?

当然,您可以创建另一个函数

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

但我想知道是否还有其他的方法。

(我知道index % size是一种非常幼稚的方式来做我想做的事情,但它不是我问题的焦点,使代码更小。)

编辑

当我编写这个问题时,我认为当右手边为正数时,%操作符将始终返回正数,就像在python中那样。我把原来的问题放在这里只是为了保持一致。


由于get操作符已经在List中定义,因此不能用一个Int参数重新定义get。但是,您可以重写invoke操作符,这在List中没有定义。

1
2
3
4
5
6
7
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))

尽管我认为用适当的名称为List创建一个新的扩展方法将是更可取的选择。

旁注,(positive value) % (negative value)为非负,(negative value) % (positive value)为非正。Kotlin中的%对应于haskell中的rem,示例如下:https://stackoverflow.com/a/28027235/869330


您正在尝试一些不可能的方法,因为扩展总是被成员隐藏,即使是@JvmName也无法保存您。

解决方法:使用第二个解决方案,或者添加一个不好看(看起来像a[x, Unit],但可以与自己的get方法一起存在的Unit参数。

另一个解决方案:创建自己的List实现(推荐)。