Why Kotlin can not override List<*> operator me

2019-07-29 04:13发布

问题:

Here is my function:

operator  infix fun  List<Teacher>.get(int: Int): Teacher {
    var t = Teacher()
    t.name = "asd"
    return t ;
}

and my usage:

b[0].teachers[1].name

tip: b is an object that has List< Teacher > property

and the errorEmpty list doesn't contain element at index 1.

why this override operator function doesn't work?

回答1:

In Kotlin, you cannot shadow a member function with an extension. A member always wins in the call resolution. So, you basically cannot call an extension with a signature same to that of a member function, that is present in the type that was declared or inferred for the expression.

class C {
    fun foo() { println("member") }
}

fun C.foo() { println("extension") }

C().foo() // prints "member"

In your case, the member function is abstract operator fun get(index: Int): E defined in kotlin.collections.List.

See the language reference: Extensions are resolved statically



回答2:

As voddan mentions in the comment, you can't overshadow a method with an extension. However, there is a way to get around this with some polymorphism. I don't think I would recommend doing this in your case, but I guess it shows off a cool Kotlin feature.

If b[0] returns an object of type B, you could do this in that class:

data class B(private val _teachers: List<Teacher> = emptyList()) {
    private class Teachers(private val list: List<Teacher>) : List<Teacher> by list {
        override operator fun get(int: Int): Teacher {
            var t = Teacher() 
            t.name = "asd"
            return t ;
        }
    }

    val teachers: List<Teacher> = Teachers(_teachers)
}

fun main(args: Array<String>) {
    println(B().teachers[0].name) // Prints "asd"
}

When I override the get-function it will affect everyone that uses the B class, not just where you would import the extension-function.

Note that I am delegating all other method-calls on the Teachers-class through to the underlying list.



标签: kotlin