Kotlin: Scope Functions
Scope functions are functions that execute a block of code within the context of an object.
Scope functions provides a way to give temporary scope to the object, where specific operations can be applied to the object within the block of code.
Scope functions make your code more concise and readable.
In Kotlin, scope functions are a set of functions that are used to perform operations on objects within a specific context, often referred to as the receiver object. These scope functions allow you to execute a block of code while providing a concise and expressive way to work with objects, set properties, or perform operations on them. They are particularly useful for reducing redundancy, improving code readability, and managing variable scopes.
Example: Without using scope function
class KRDCompany() {
lateinit var name: String
lateinit var objective: String
lateinit var founder: String
}
fun main() {
// without using scope function
// creating instance of KRDCompany Class
val krd = KRDCompany()
// initializing members of the class
krd.name = “TutorialsExample”
krd.objective = “A tutorials portal”
krd.founder = “Rajnish “
println(krd.name)
}
Output:
TutorialsExample
It’s apparent that, in the absence of scope functions, we are required to include the object name each time we wish to access class members. Conversely, when employing scope functions, direct reference to members can be made without the need for the object name. This represents one of the practical applications of scope functions, which we will explore further in this article.
You might have observed that, without the use of scope functions, repetitive object naming is essential for accessing class members. In contrast, scope functions enable us to access members directly, eliminating the need for object names. This constitutes one of the methods for leveraging scope functions, and we’ll delve deeper into their usage throughout this article.
It’s worth noting that, in the absence of scope functions, it’s obligatory to specify the object name whenever we want to access class members. Conversely, with the use of scope functions, we have the liberty to reference members directly, sans the object name. This is one of the practical applications of scope functions, and we’ll delve into them further in this article.
Types of scope functions
There are five types of scope functions:
- let
- run
- with
- apply
- also
Differences in these functions:
There are mainly two differences among these functions:
- Way of referring to a context object (i.e. using either ‘this’ or ‘it’ keyword)
- return value (i.e. returns either ‘context object’ or ‘lambda result’)
These scope functions provide different ways to work with objects, manage variable scopes,
Scope Function | Primary Use Case | Return Value |
---|---|---|
let |
Perform operations on nullable objects and transform them. | Result of the lambda expression. |
run |
Execute code on non-nullable objects and access their properties/methods. | Result of the lambda expression. |
with |
Simplify access to properties/methods of an object (non-extension function). | Result of the lambda expression. |
apply |
Initialize or configure an object (non-extension function). | The modified object itself. |
also |
Perform side effects or logging on an object (non-extension function). | The original object itself. |
Function |
Object Reference |
Return Value |
---|---|---|
let |
it |
Lambda result |
run |
this |
Lambda result |
with |
this |
Lambda result |
apply |
this |
Context object |
also |
it |
Context object |
1. let function
let function is often used to provide null safety calls. Use safe call operator(?.) with ‘let’ for null safety. It executes the block only with the non-null value.
fun main() {
// Declare a nullable variable ‘number’ with an initial value of null.
var number: Int? = null
// Use the ‘let’ function to perform operations when ‘number’ is not null.
number?.let {
// These statements will not execute because ‘number’ is null.
print(it)
}
// Re-initialize the value of ‘number’ to 2.
number = 2
// Use the ‘let’ function again to perform operations when ‘number’ is not null.
number?.let {
// These statements will execute because ‘number’ is not null.
print(number)
}
}
Hi
Good explanation, need full article.