¿Puedo enviar la function de extensión a través del parámetro de function?

Tengo algunas funciones de extensión a continuación.

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 } 

Tanto setEmailValidationListener como setPasswordValidationListener son idénticos, excepto por la function de validation que utilizan respectivamente, es decir validateEmailFormat y validatePasswordFormat .

Así que planeo refactorizar el código común de dos funciones en una function común como la siguiente

 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 } 

… donde básicamente es solo para enviar validationFunc como parámetro para ello.

Sin embargo, no puedo encontrar ninguna forma de enviar EditText.validateEmailFormat y EditText.validatePasswordFormat al parámetro de function validationFunc .

¿Cómo podría lograr eso?

Alguna teoría

La firma de las funciones de extensión es un poco más complicada de lo que se puede ver al principio. La extensión necesita tener alguna reference al object de esta class para poder actuar sobre ella.

De hecho, el método de extensión

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

después de descomstackr en Java antiguo, se ve así:

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

Como es (casi) imposible cambiar la class de Java ya comstackda. Así que Kotlin (y posiblemente otros lenguajes que tienen un concepto de methods de extensión) utiliza methods estáticos, con el primer parámetro que es el receptor de la class que se extiende, para que funcione.

Regreso al negocio

Su validateEmailFormat es de hecho de tipo EditText.(Boolean) -> Boolean y al mismo time es de tipo (EditText, Boolean) -> Boolean . Entonces debes hacer una de estas dos cosas:

Primero puede hacer que EditText.setupTextChangeListener acepte validatorFunc como EditText.(Boolean) -> Boolean o (EditText, Boolean) -> Boolean lugar de (Boolean) -> Boolean .

O puede abstenerse de extender EditText en el modo fun EditText.validateEmailFormat(Boolean) y dejar en claro la function de Kotlin, por ejemplo, algo así como fun EditText.validateEmailFormat(Boolean) fun validateEmailFormat(String, Boolean) .

Como está utilizando ampliamente las funciones de extensión, asumo que la primera opción es la solución correcta para usted.

  • ¿Cómo colocar una extensión de Kotlin en un file de class?
  • Función de extensión booleana
  • Kotlin: ¿Cómo ejecutar methods de service en el context de una class de transacción?
  • Tokens inesperados (uso; para separar expresiones en la misma línea)
  • ¿Cómo crear una class estática en Kotlin?
  • La function de extensión no crea un nuevo object Observable
  • El resultado es el mismo, pero el caso de testing no pasa en la testing unitaria
  • ¿Cómo extiendo la class Kotlin Number o uso generics para crear un getter de propiedad simple que operará en todas las subclasss Number?
  • En kotlin, cómo devolver una instancia definida por un parámetro de class genérico
  • Genéricos para RecyclerView.Adapter Android
  • ¿Cómo verificar la class "instanceof" en kotlin?