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

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

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

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