Kotlin Scoped Functions: Code Smarter in 2025! 🚀
Inside these blocks, the object is accessed as either “it” or “this”—your choice shapes the magic!
Exploring Scoped Functions with Examples
Kotlin offers five scoped functions: let, run, with, also, and apply. Let’s dive in with a Person class:
class Person {
var name: String = "Abcd"
var contactNumber: String = "1234567890"
var address: String = "xyz"
fun displayInfo() = print("\nName: $name\n" +
"Contact Number: $contactNumber\n" +
"Address: $address") // Person snapshot 📋
}
Let 🔍
The let function runs a block on an object and returns the block’s result:
private fun performLetOperation() {
val person = Person().let {
"The name of the Person is: ${it.name}"
}
print(person) // Outputs: The name of the Person is: Abcd
}
Let Highlights:
- 🔍 Uses it to refer to the object—renamable (e.g., personDetails).
- ⚡ Returns the lambda’s result, not the object (here, a string).
- ✅ Perfect for null checks with ?.let.
Rename it for clarity:
private fun performLetOperation() {
val person = Person().let { personDetails ->
personDetails.name = "NewName"
personDetails // Returns the Person object
}
person.displayInfo() // Outputs: Name: NewName...
}
Null Safety: Check nullable properties cleanly:
class Person {
var name: String? = null
}
fun main() {
val p = Person()
p.name?.let { println(it) } ?: println("Name is null") // Outputs: Name is null
}
Call Chain: Operate on chain results:
fun main() {
val numbers = mutableListOf("One", "Two", "Three", "Four", "Five")
numbers.map { it.length }.filter { it > 3 }.let {
print(it) // Outputs: [5, 4] (lengths > 3)
}
}
Scope Limiting: Define variables for a specific block:
webView.settings?.let { setting ->
setting.javaScriptEnabled = true
setting.domStorageEnabled = true
setting.userAgentString = "mobile_app_webview"
} // 'setting' isn’t accessible outside
Run ⚡
Run blends with and let—it uses this and returns the lambda’s result:
private fun performRunOperation() {
val name = Person().run {
"The name of the Person is: $name" // 'this' is optional
}
print(name) // Outputs: The name of the Person is: Abcd
}
Run vs Let:
- ⚡ run uses this (can’t rename); let uses it (renamable).
- ✅ Both handle null checks with ?.run or ?.let.
- 🔄 Both return the lambda’s result—flexible output.
Chain Example:
webView.settings?.run {
javaScriptEnabled = true
domStorageEnabled = true
userAgentString = "mobile_app_webview"
webView // Return the WebView
}.run {
webViewClient = MyWebViewClient()
loadUrl(mUrl)
"Loaded!" // Return a string
}
With 🧰
With operates on an object using this, ideal for multiple method calls without dot repetition:
with(webView.settings) {
javaScriptEnabled = true
domStorageEnabled = true
userAgentString = "mobile_app_webview"
webView // Returns WebView
}
With vs Run:
- 🧰 with isn’t an extension function—takes the object as an argument.
- ⚡ run handles null safety (?.run); with doesn’t naturally.
- ✅ Both use this and return the block’s result.
Null Challenge:
private fun performWithOperation() {
val person: Person? = null
with(person) {
this?.name = "asdf" // Clunky null check
}
}
Apply 🔧
Apply configures an object and returns it—great for initialization:
private fun performApplyOperation() {
val person = Person().apply {
name = "asdf"
contactNumber = "1234"
address = "wasd"
}
person.displayInfo() // Returns modified Person
}
Apply vs Run:
- 🔧 apply returns the object; run returns the lambda result.
- ✅ Both use this and support null safety (?.apply).
- ⚡ apply can’t rename the context.
Chain Example:
webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
userAgentString = "mobile_app_webview"
}.let {
webView // Switch context
}.apply {
webViewClient = MyWebViewClient()
loadUrl(mUrl)
}
Android Use Case: Configuring an Intent:
val intent = Intent("com.example.ACTION").apply {
putExtra("key", "value")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
} // Ready-to-use Intent
Also 📝
Also runs a block and returns the object, using it:
private fun performAlsoOperation() {
val person = Person().also {
print("Current name is: ${it.name}\n")
it.name = "ModifiedName"
}
person.displayInfo() // Returns modified Person
}
Also vs Let:
- 📝 also returns the object; let returns the lambda result.
- ✅ Both use it and support null checks (?.also).
- ⚡ also is great for side effects in chains.
Chain Example:
webView.settings.also { setting ->
setting.javaScriptEnabled = true
setting.domStorageEnabled = true
setting.userAgentString = "mobile_app_webview"
}.run {
webView
}.also {
it.webViewClient = MyWebViewClient()
it.loadUrl(mUrl)
}
Images for reference:
Quick Comparison Table 🤔
Here’s a handy table to sum up the scoped functions:
Function | Context Reference | Returns | Best Use Case |
---|---|---|---|
let | it | Lambda result | Transformation, null checks |
run | this | Lambda result | Object configuration |
with | this | Lambda result | Grouping method calls |
apply | this | The object itself | Modifying and returning an object |
also | it | The object itself | Debugging, side effects |
Table Notes:
- 🔍 Context Reference: How the object is accessed inside the block.
- ⚡ Returns: What you get after the block runs.
- ✅ Best Use Case: When to pick each function.
..
Comments
Post a Comment