我可以通过函数参数发送扩展函数吗
Can I send extension function through function parameter
我下面有一些扩展函数function。
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
}
setEmailValidationListener
和 setPasswordValidationListener
是相同的,除了它们分别使用的验证函数,即 validateEmailFormat
和 validatePasswordFormat
。
所以我打算将两个函数的公共代码重构为一个公共函数如下
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.validateEmailFormat
和 EditText.validatePasswordFormat
发送到 validationFunc
函数参数中。
我怎样才能做到这一点?
一些理论
扩展函数的签名比乍一看要复杂一些。扩展需要引用此 class 的对象才能对其进行操作。
其实扩展方法
fun EditText.validateEmailFormat(showError: Boolean = true): Boolean
反编译为普通的旧 java 后,看起来像这样:
public static final boolean validateEmailFormat(@NotNull EditText $receiver, boolean showError)
因为(几乎)不可能更改已编译的 Java class。因此 Kotlin(很可能还有其他具有扩展方法概念的语言)使用静态方法,第一个参数是扩展的接收者class,以使其工作。
回到正题
你的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)
.
由于您广泛使用扩展函数,我认为第一个选项对您来说是正确的解决方案。
fun EditText.validateEmailFormat()
可以传递为 EditText::validateEmailFormat
.
我下面有一些扩展函数function。
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
}
setEmailValidationListener
和 setPasswordValidationListener
是相同的,除了它们分别使用的验证函数,即 validateEmailFormat
和 validatePasswordFormat
。
所以我打算将两个函数的公共代码重构为一个公共函数如下
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.validateEmailFormat
和 EditText.validatePasswordFormat
发送到 validationFunc
函数参数中。
我怎样才能做到这一点?
一些理论
扩展函数的签名比乍一看要复杂一些。扩展需要引用此 class 的对象才能对其进行操作。
其实扩展方法
fun EditText.validateEmailFormat(showError: Boolean = true): Boolean
反编译为普通的旧 java 后,看起来像这样:
public static final boolean validateEmailFormat(@NotNull EditText $receiver, boolean showError)
因为(几乎)不可能更改已编译的 Java class。因此 Kotlin(很可能还有其他具有扩展方法概念的语言)使用静态方法,第一个参数是扩展的接收者class,以使其工作。
回到正题
你的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)
.
由于您广泛使用扩展函数,我认为第一个选项对您来说是正确的解决方案。
fun EditText.validateEmailFormat()
可以传递为 EditText::validateEmailFormat
.