Как исправить сигнатуру универсального метода расширения в kotlin для разрешения ошибки вывода типа в kotlin

Я создал метод расширения:

@Suppress("UNCHECKED_CAST")
operator fun <T : View> View.get(@IdRes id:Int): T  =
        this.findViewById(id) as T

Основное использование этого метода:

class A {
    lateinit var text: TextView

    fun init(view:View) {
        text = view[R.id.text]
    }
}

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

fun test() {
    view[R.id.text].visibility = View.GONE // error
}

Ошибка:

Type inference failed: Not enough information to infer parameter T in 
operator fun <T : View> View.get(id: Int): T
Please specify it explicitly.

Если я пишу аналогичный код на java, то методы класса View доступны без прямого указания типа View.

Возможно ли это в котлине? Может быть, как-то изменить сигнатуру универсального типа?


person curioushikhov    schedule 04.08.2017    source источник
comment
Я предполагаю, что Java просто по умолчанию использует привязку T, если она действительна, а Kotlin - нет.   -  person Jorn Vernee    schedule 04.08.2017
comment
Я нашел обходной путь view.get‹View›(R.id.text) = View.GONE, но в этом случае я предпочитаю view.findViewById(R.id.text), потому что скобки добавляют много шума при разборе операторов при чтении.   -  person curioushikhov    schedule 04.08.2017
comment
С Kotlin вы можете легко избавиться от findViewById: kotlinlang.org/docs/tutorials/android- плагин.html   -  person Miha_x64    schedule 05.08.2017
comment
На данный момент для меня это бесполезно, потому что он не поддерживает фрагменты, вы не можете контролировать, когда привязывать представление к полям, как это делает Butterknife, и это весело терпит неудачу для динамических макетов.   -  person curioushikhov    schedule 05.08.2017


Ответы (1)


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

Вы можете вызывать функцию get как обычную функцию view.get<TextView>(R.id.text), не используя соглашение о перегрузке операторов.

Для достижения желаемой функциональности вы можете использовать расширения Kotlin для Android, предложенные @Miha_x64, без необходимости использовать метод findViewById.

person Diego Malone    schedule 16.06.2018