Как сделать метод param изменчивым в Kotlin?

Я реализую проект SpinnerAdapter в Android. Поэтому я должен переопределить getView(i: Int, convertView: View, parent: ViewGroup) . Таким образом, convertView здесь используется для повторного использования существующего представления и сокращения использования памяти и появления GC. Поэтому, если это null мне нужно создать представление и использовать уже созданные в противном случае.

Поэтому на самом деле мне нужно написать что-то вроде этого (официально рекомендованное google):

 if (view == null) { view = View.inflate(context, R.layout.item_spinner, parent) view.tag(Holder(view)) } else { (view.tag as Holder).title.text = getItem(i) } 

Но Котлин не позволяет писать в param. То, что я нашел в Интернете, является официальным сообщением в блоге, в котором говорится, что это невозможно с февраля 2013 года.

Так что мне интересно, есть ли способ обхода?

Здесь есть два вопроса.

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

 View getView(int i, View view, ViewGroup parent) { // modify view here does nothing to the original caller reference to view // but returning a view does do something } 

Далее, в Котлине все параметры являются final (модификатор JVM, также как и final модификатор в Java). Версия инструкции Kotlin if этого кода будет:

 fun getView(i: Int, view: View?, parent: ViewGroup): View { return if (view == null) { val tempView = View.inflate(context, R.layout.item_spinner, parent) tempView.tag(Holder(tempView)) tempView } else { (view.tag as Holder).title.text = getItem(i) view } } 

или избежать новой локальной переменной:

 fun getView(i: Int, view: View?, parent: ViewGroup): View { return if (view == null) { View.inflate(context, R.layout.item_spinner, parent).apply { tag(Holder(this)) // this is now the new view } } else { view.apply { (tag as Holder).title.text = getItem(i) } } } 

или

 fun getView(i: Int, view: View?, parent: ViewGroup): View { if (view == null) { val tempView = View.inflate(context, R.layout.item_spinner, parent) tempView.tag(Holder(tempView)) return tempView } (view.tag as Holder).title.text = getItem(i) return view } 

или используя ?. и ?: null операторов в сочетании с apply() :

 fun getView(i: Int, view: View?, parent: ViewGroup): View { return view?.apply { (tag as Holder).title.text = getItem(i) } ?: View.inflate(context, R.layout.item_spinner, parent).apply { tag(Holder(this)) } } 

И есть еще 10 вариантов, но вы можете поэкспериментировать, чтобы увидеть, что вам нравится.

Это считается менее эффективной практикой (но допускаемой) для теневых переменных с использованием одного и того же имени, поэтому это предупреждение компилятора. И почему вы видите изменение в названии переменной выше из view в tempView

Официально говоря, вы не можете переопределить параметр метода. Лучшее, что вы можете сделать, это «тень» переменной param.

Таким образом, вы можете сделать это схожим (не уверен, почему вы хотели бы тень, но вы можете)

 getView(i: Int, view: View?, parent: ViewGroup) { val view = view ?: View.inflate(context, R.layout.item_spinner, parent) .apply { tag(Holder(view)) } (view.tag as Holder).title.text = getItem(i) } 

Измененные параметры не поддерживаются в Котлине.

Я хотел бы сослаться на эту дискуссию на kotlinlang.org .

Для этого есть грязный, но полезный способ.

 fun a(b: Int) { var b = b b++ // this compiles }