2016-08-19 87 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