2016-08-19 57 views
1

发送扩展功能我在下面有一些扩展功能功能。我可以通过功能参数

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 
} 

两个setEmailValidationListenersetPasswordValidationListener是相同的,除了验证函数它们分别使用即validateEmailFormatvalidatePasswordFormat

所以我打算重构两种功能共同的代码放到一个共同的功能如下

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.validateEmailFormatEditText.validatePasswordFormat发送到validationFunc函数参数的方法。

我怎么能做到这一点?

回答

6

一些理论的扩展功能

签名比可以看第一位更加复杂。该扩展需要对该类的对象有一定的参考才能对其采取行动。

事实上的扩展方法

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

反编译后,对普通旧式Java,看起来是这样的:

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

由于这是(几乎)不可能改变已编译的Java类。所以Kotlin(很可能有其他语言有扩展方法的概念)使用静态方法,第一个参数是扩展类的接收器,以使其工作。

回到业务

validateEmailFormatEditText.(Boolean) -> Boolean类型的事实,并在同一时间(EditText, Boolean) -> Boolean类型。所以,你需要做的两件事情之一:

首先,你可以让EditText.setupTextChangeListener接受validatorFuncEditText.(Boolean) -> Boolean(EditText, Boolean) -> Boolean代替(Boolean) -> Boolean

或者您不要在fun EditText.validateEmailFormat(Boolean)中延伸EditText,并使其具有普通的Kotlin功能,例如,像这样fun validateEmailFormat(String, Boolean)

由于您正在广泛使用扩展函数,因此我假设第一个选项对您而言是正确的解决方案。

+2

除了上面的解释,我建议增加一个使用'validatorFunc:EditText。(showError:Boolean) - > Boolean'的例子。例如:'editText.setupTextChangeListener(EditText :: validateEmailFormat)' – mfulton26

+0

绝对喜欢! – Elye