为什么委托 class 方法的 getValue 和 setValue 需要用 operator 关键字标记?

Why do delegate class methods getValue and setValue need to marked with operator keyword?

这是 Delegated properties 文档中的示例。

import kotlin.reflect.KProperty

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

我不确定我是否正确理解了您的问题,但我们添加了 operator 以将函数标记为不仅仅是常规函数,而是指定用于提供某些特定功能的函数。这并不局限于委托属性——它对所有操作符都是一样的。

我认为标记为运算符至少有两个好处。首先,reader 明确表示该函数可以与某些语言特性一起使用。其次,它有助于避免我们打算提供一些操作员但我们犯了错误的情况,例如在参数类型中,所以它被默默地忽略了。 operator 立即告诉我们函数签名是否正确。

这是因为委托属性是 defined by convention。这意味着:

[its] semantics are defined through syntactic expansion of one syntax form into another syntax form.

可以看到委托的扩展属性 further down the documentation page:

class C {
    var prop: Type by MyDelegate()
}

// this code is generated by the compiler instead:
class C {
    private val prop$delegate = MyDelegate()
    var prop: Type
        get() = prop$delegate.getValue(this, this::prop)
        set(value: Type) = prop$delegate.setValue(this, this::prop, value)
}

按照惯例定义的语法特征之一是(从第一个 link 开始):

All call expressions that are produced by expansion are only allowed to use operator functions.

还有:

This expansion of a particular syntax form to a different piece of code is usually defined in the terms of operator functions.

只是为了给您提供更多示例,第一个 link 显示了更多按约定定义的语法示例。下面是与它们相关的相应运算符函数:

Syntax defined by convention Related operator functions
Arithmetic and comparison operators plus, compareTo etc
invoke convention invoke
Operator-form assignments plusAssign, minusAssign etc
For-loop statements iterator, hasNext, next
Delegated properties setValue, getValue
Destructuring declarations component1, component2 etc

请注意,您需要在所有这些函数上加上单词 operator 才能使相应的语法起作用。换句话说,“operator”表示该函数可以在约定定义的语法中使用。