Intereting Posts
Kotlin Coroutines с таймаутом IntelliJ не распознает файл kotlin после его удаления и воссоздает с тем же именем Котлин проверял исключения Свойства делегата Kotlin, реализующие функцию оператора «предоставлятьDelegate», но метод никогда не вызывал Android Kotlin – адаптер ListView из списка объектов JsonArray в класс данных Kotlin с использованием Retrofit (ожидается BEGIN_OBJECT, но BEGIN_ARRAY) ojAlgo Линейная оптимизация – предотвращение дублирования рабочей смены? Android: выполнение Kotlin завершилось неудачно, пытаясь использовать Databinding Плагин Android-плагинов жалуется на ошибку перевода Uncaught Kotlin readBytes () никогда не завершает правильное поведение сопрограмм? Я получаю ошибку неоднозначности разрешения перегрузки при безопасном вызове kotlin Как отлаживать последовательности / коллекции Котлина Невозможно остановить исключение в IntelliJ IDEA при написании кода Котлина Как буферизировать бесконечный прослушиватель прокрутки

Могу ли я отправить функцию расширения через параметр функции

У меня есть функция расширения функций ниже.

fun EditText.setEmailValidationListener(): TextWatcher { val textWatcher = object : TextWatcher { override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { } override fun afterTextChanged(text: Editable?) { validateEmail() } private fun validateEmail(): Boolean { if (validateEmailFormat(showError = false)) { getParentInputLayout()?.isErrorEnabled = false return true } return false } } addTextChangedListener(textWatcher) return textWatcher } fun EditText.setPasswordValidationListener(): TextWatcher { val textWatcher = object : TextWatcher { override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { } override fun afterTextChanged(text: Editable?) { validateEmpty() } private fun validatePasswordText(): Boolean { if (validateEmptyText(showError = false)) { getParentInputLayout()?.isErrorEnabled = false return true } return false } } addTextChangedListener(textWatcher) return textWatcher } fun EditText.validateEmailFormat(showError: Boolean = true): Boolean { // Do something checking the Email return false } fun EditText.validatePasswordText(showError: Boolean = true): Boolean { // Do something checking the Password return false } private fun EditText.getParentInputLayout(): TextInputLayout? { if (parent is TextInputLayout) { return parent as TextInputLayout } return null } 

И setEmailValidationListener и setPasswordValidationListener идентичны, за исключением функции проверки, которую они используют соответственно, т.е. validateEmailFormat и validatePasswordFormat .

Поэтому я планирую реорганизовать два общих кода функции в общую функцию, как показано ниже

 fun EditText.setupTextChangeListener(validatorFunc : (showError: Boolean) -> Boolean): TextWatcher { val textWatcher = object : TextWatcher { override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { } override fun afterTextChanged(text: Editable?) { validateEmpty() } private fun validateEmpty(): Boolean { if (validatorFunc(false)) { getParentInputLayout()?.isErrorEnabled = false return true } return false } } addTextChangedListener(textWatcher) return textWatcher } 

… где он в основном просто для отправки в validationFunc как параметр к нему.

Однако я не могу найти способ отправки EditText.validateEmailFormat и EditText.validatePasswordFormat в параметр функции validationFunc .

Как я мог это достичь?

Некоторая теория

Подпись функций расширения немного сложнее, чем может выглядеть вначале. Расширение должно иметь некоторую ссылку на объект этого класса, чтобы иметь возможность воздействовать на него.

Фактически метод расширения

 fun EditText.validateEmailFormat(showError: Boolean = true): Boolean 

после декомпиляции простой старой java, выглядит так:

 public static final boolean validateEmailFormat(@NotNull EditText $receiver, boolean showError) 

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

Вернуться к делу

Ваш validateEmailFormat на самом деле имеет тип EditText.(Boolean) -> Boolean и в то же время имеет тип (EditText, Boolean) -> Boolean . Поэтому вам нужно сделать одну из двух вещей:

Сначала вы можете сделать EditText.setupTextChangeListener принимать validatorFunc как EditText.(Boolean) -> Boolean или (EditText, Boolean) -> Boolean вместо (Boolean) -> Boolean .

Или вы воздерживаетесь от расширения EditText в fun EditText.validateEmailFormat(Boolean) и делаете его простой функцией Kotlin, например, что-то вроде этого fun validateEmailFormat(String, Boolean) .

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