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

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

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

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

Intereting Posts
Spring & kotlin: В чем разница между инсталляцией конструктора и латинита? Несогласованность получения данных из базы данных Firebase с тем же классом данных Как я могу сделать это для многих переменных Текстовый объект объекта Kotlin, реализующий дикий кардочесальный, саморегуляторный общий интерфейс Создать конкретный Java-класс, который использует рекурсивные дженерики в Котлине Ручка ACTION_UP в OnLongPress Android Есть ли какая-либо ссылка на временную сложность библиотеки коллекции Kotlin? JDK требуется для Kotlin? Kotlin и Gradle – Чтение из stdio Значение параметра Proto3, равное по умолчанию, не распознается во время выполнения Зачем связывать объекты буфера OpenGL? Как улучшить синтаксис лямбда kotlin? Комната Kotlin: У сущностей и Pojos должен быть полезный публичный конструктор kapt2 и butterknife производят ошибку lint: ожидаемый ресурс идентификатора типа IntelliJ Idea при тестировании сразу нескольких модулей включаются только артефакты из одного модуля