Also published on my blog here: https://iamvishnu.com/posts/kotlin-extension-functions
Kotlin has this nice feature called "Extension Functions" — adding new functionality to an existing class, without inheritance or writing lots of boilerplate code. Extension functions and extension properties are allowed in Kotlin.
Here is an example Extension for the Float
class by adding a new function called asDollars()
to print that float number as a currency value:
fun Float?.asDollars() = "USD%.2f".format(this ?: 0.0F)
Now anywhere in code I can write:
val money = 42.0F
println( money.asDollars() ) // will print "USD42.00"
Note: An extension function doesn't really modify the existing class. Instead, the receiver object is passed as the first parameter during compile time. For more, read: Extension functions are resolved statically.
Here are some of my own Extensions that I use across many projects in Android:
1. Some AlertDialogs
fun Context.showAlertDialog(
title: String,
message: String,
ok: Pair<String,()->Unit>,
cancel: Pair<String,()->Unit>? = null){
val builder = AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton(ok.first) { _,_ -> ok.second() }
cancel?.let{
builder.setNegativeButton(it.first) { _, _ -> it.second() }
}
builder.create().show()
}
fun Context.showConfirmDialog(
title: String,
message: String,
ok: Pair<String,()->Unit>,
cancel: Pair<String,()->Unit>? = null
) = showAlertDialog(title, message, ok, cancel)
fun Context.showErrorDialog(message: String, action: () -> Unit){
showAlertDialog(
title = "Error",
message = message,
ok = "OK" to action
)
}
Usage on Activity (or Fragments):
fun onResume(){
showAlertDialog(
title = "Welcome",
message = "Hello, welcome to the show! Do you want to proceed?",
ok = "Yes" to { nextScreen() },
cancel = "No" to { finish() }
)
// showing an error
showError("No internet connection. Please try later") { finish() }
}
2. A Simple Click Listener
inline fun View.onClick(crossinline f: ()-> Unit) = this.setOnClickListener { f() }
Usage:
btnNext.onClick { nextScreen() }
3. Some EditText
validations
fun isValidText(s: String?) = s!=null && !s.isEmpty()
fun isValidEmail(s: String?) = isValidText(s) && android.util.Patterns.EMAIL_ADDRESS.matcher(s).matches()
fun EditText.trimmedText() = this.text?.trim().toString()
fun EditText.isValidText() = isValidText(this.trimmedText())
fun EditText.isValidEmail() = isValidEmail(this.trimmedText())
Usage:
isValidForm = editEmail.isValidEmail() && editUsername.isValidText()
What are your favorite Extension Functions / Properties that you have authored for your projects?
I really liked the
onClick
extension. But I slightly disagree with some of the extensions. Kotlin extensions are a way of implementing theOpen Closed
Principle. Classes remain closed for modification and open for extension. But are the extension really a responsibility of the class? For example,Float.asDollar()
, does float class should be aware of anything related to currencies. In my opinionFloat
class should be exposing functions only related to decimal point numbers, not really converting it to a very specific string format. Similar is my opinion aboutContext.showAlertDialog
. While we require the help ofContext
to build an alert dialog, showing it is might not be the responsibility ofContext
. What do you think?