Почему методы делегированного класса GetValue и setValue должны быть отмечены ключевым словом operator?

#kotlin #kotlin-delegate

Вопрос:

Вот пример из документации по делегированным свойствам.

 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.")
    }
}
 

Ответ №1:

Это связано с тем, что делегированные свойства определяются соглашением. Это означает:

[его] семантика определяется путем синтаксического расширения одной синтаксической формы в другую синтаксическую форму.

Вы можете увидеть расширение делегированного свойства далее на странице документации:

 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)
}
 

И одной из характеристик синтаксиса, который определяется соглашением, является то, что (из первой ссылки):

Всем выражениям вызова, созданным расширением, разрешено использовать только операторные функции.

а также:

Это расширение определенной синтаксической формы в другую часть кода обычно определяется в терминах операторных функций.

Просто чтобы дать вам больше примеров, первая ссылка показывает больше примеров синтаксиса, которые определены соглашением. Вот соответствующие операторные функции, связанные с ними:

Синтаксис определяется соглашением Связанные функции оператора
Операторы арифметики и сравнения plus и т. compareTo Д
invoke соглашение invoke
Назначения операторной формы plusAssign и т. minusAssign Д
Операторы For-цикла iterator , hasNext , next
Делегированные свойства setValue , getValue
Объявления деструктурирования component1 и т. component2 Д

Обратите внимание, что вам нужно поместить слово operator во все эти функции, чтобы работал соответствующий синтаксис. Другими словами, « operator » означает, что эта функция может использоваться в синтаксисе, определенном соглашением.

Ответ №2:

Я не уверен, правильно ли я понял ваш вопрос, но мы добавляем operator функции для обозначения не просто обычных функций, а функций, предназначенных для обеспечения определенной функциональности. На самом деле это не ограничивается делегированными свойствами — оно одинаково для всех операторов.

Я думаю, что маркировка как операторы имеет как минимум два преимущества. Во-первых, для читателя очевидно, что функция может использоваться с некоторой языковой функцией. Во-вторых, это помогает избежать ситуаций, когда мы намеревались предоставить некоторый оператор, но допустили ошибку, например, в типах параметров, поэтому он молча игнорируется. operator сразу сообщает нам, правильна сигнатура функции или нет.