Принудительно указать параметр типа, чтобы он был инвариантным на сайте использования, когда он ковариантен на сайте объявлений.

Я строю функцию расширения на KProperty1, Функция должна принимать аргумент, расширяющий тип значения свойства (R), даже если KProperty1 ковариантен в параметре типа R,

Немного придуманный пример будет следующим, хотя мое использование более законно.

data class Data(val value: String)

fun <V> KProperty1<*, V>.setMagically(value: V) {
    this.javaField?.set(null, value)
}

fun test() {
    // I would like this to fail to compile
    Data::value.setMagically(190)
}

Казалось бы, компилятор выводит тип Any за R, который полностью действителен, так как KProperty1<*, String> : KProperty1<*, Any>

Я хочу сказать, что для моего конкретного случая я действительно хочу V быть инвариантным. Я знаю, что вы можете использовать out а также in как расширение дисперсии, но я не смог понять, как указать, что я хочу переопределить ковариантную аннотацию на KProperty1 с неизменностью для этого случая.

Стоит отметить, что он прекрасно работает с KMutableProperty1, поскольку это инвариант в R, Но мой код должен работать и с неизменяемыми свойствами.

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

1 ответ

Решение

В настоящее время это невозможно в Котлине. На самом деле, есть внутренняя аннотация, которая включает это поведение (заставляет компилятор сообщать об ошибке, если Any выводится, хотя нигде на сайте вызова не было упомянуто), и он используется в нескольких местах в kotlin-stdlib, но использовать его за пределами стандартной библиотеки по-прежнему не рекомендуется.

У нас есть планы сделать эту аннотацию публичной. Для более подробной информации, пожалуйста, проверьте KT-13198.

Другие вопросы по тегам