【问题标题】:Can I send extension function through function parameter我可以通过函数参数发送扩展函数吗
【发布时间】:2016-08-19 02:32:50
【问题描述】:

我下面有一些扩展函数函数。

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 函数参数的任何方法。

我怎样才能做到这一点?

【问题讨论】:

    标签: android kotlin kotlin-extension


    【解决方案1】:

    一些理论

    扩展函数的签名比最初看起来要复杂一些。扩展需要对此类的对象进行一些引用才能对其进行操作。

    其实就是扩展方法

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

    反编译成普通的旧java后,如下所示:

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

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

    回到正题

    您的validateEmailFormat 实际上是EditText.(Boolean) -> Boolean 类型,同时也是(EditText, Boolean) -> Boolean 类型。所以你需要做两件事之一:

    首先你可以让EditText.setupTextChangeListener 接受validatorFunc 作为EditText.(Boolean) -> Boolean(EditText, Boolean) -> Boolean 而不是(Boolean) -> Boolean

    或者你避免在 fun EditText.validateEmailFormat(Boolean) 中扩展 EditText 并使其成为普通的 Kotlin 函数,例如像这样fun validateEmailFormat(String, Boolean)

    由于您广泛使用扩展功能,我认为第一个选项对您来说是正确的解决方案。

    【讨论】:

    • 除了上面的解释,我建议添加一个使用validatorFunc: EditText.(showError: Boolean) -> Boolean的例子。例如:editText.setupTextChangeListener(EditText::validateEmailFormat)
    • 绝对喜欢!
    【解决方案2】:

    fun EditText.validateEmailFormat() 可以作为EditText::validateEmailFormat 传递。

    【讨论】:

      猜你喜欢
      • 2013-11-16
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      • 2011-11-18
      • 2011-02-20
      • 2021-10-26
      • 2019-10-10
      相关资源
      最近更新 更多