2016-08-19 12 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それぞれ使用する検証機能を除いて、同一です。

は、だから私はそれが基本的にはちょうどそれをパラメータとしてvalidationFuncに送信するために

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 
} 

...以下のような一般的な関数に2つの機能の共通コードをリファクタリングする予定。

しかし、EditText.validateEmailFormatEditText.validatePasswordFormatを関数パラメータのvalidationFuncに送信する方法はありません。

どうすれば達成できますか?拡張機能の

答えて

6

いくつかの理論

署名が最初に見えるかもしれにおけるよりも少し複雑です。エクステンションは、このクラスのオブジェクトを参照できるようにする必要があります。逆コンパイル後に実際に

拡張メソッド

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

昔ながらのjavaに、次のようになります。それは既にコンパイルされたJavaクラスを変更するには(ほぼ)不可能だとして

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

。だから、Kotlin(と他の言語では拡張メソッドの概念を持っている)は、静的メソッドを使用します。戻るビジネスに

あなたvalidateEmailFormatはタイプEditText.(Boolean) -> Booleanの事実であると同時に、タイプ(EditText, Boolean) -> Booleanです。だから、二つのいずれかを実行する必要があります。

まずあなたがEditText.setupTextChangeListenerEditText.(Boolean) -> Booleanまたは(EditText, Boolean) -> Booleanの代わり(Boolean) -> BooleanとしてvalidatorFuncを受け入れることができます。

EditTextfun EditText.validateEmailFormat(Boolean)に拡張して、コトル関数を明示的にします。このようなものfun validateEmailFormat(String, Boolean)

拡張機能を広範囲に使用しているので、私は最初のオプションが正しい解決策であると仮定します。

+2

上記の説明に加えて、 'validatorFunc:EditText。(showError:Boolean) - > Boolean'を使用した例を追加することをお勧めします。例: 'editText.setupTextChangeListener(EditText :: validateEmailFormat)' – mfulton26

+0

本当に大好きです! – Elye

関連する問題