These scope functions provide the simplest way to offer temporary scope to the thing under some circumstances where specific operations will be applied to the thing within the block of code, by which we get a clean and concise code. In Software Development, things are only better understood by implementing instead of reading. So, let’s plow ahead and understand these scoped functions with some examples.
Kotlin provide some standard library by which we can execute a block of code within the context of an object There are basically five types of scope functions they are:-
- with
- let
- run
- apply
- also
These are called Scope Functions.
Example without Scope Variabe
class School() {
lateinit var classname: String
lateinit var sunject: String }
fun main() {
// creating instance of Company Class
val sc = School()
// initializing members of the class
sc.classname = "sixth class"
sc.sunject = "data structure"
println(sc.classname)
}
Output
sixth class
1. with function
This type of scope function has this as a context object and lambda result as a result value. This scope function is use if you want to operate on a non-null object.
Using with function
class School() {
lateinit var classname: String
lateinit var sunject: String }
fun main() {
val sc = School().apply {
classname = "Sixth Class"
sunject = "data structure"
}
with(sc) {
// similar to println( "${classname}" )
println(" $classname ")
}
}
2:-let function
This type of scope function has it as a context object and lambda result as a result value. This scope function is use if you want to just execute lambda expression on a nullable object and avoid NullPointerException.
Using let function
fun main() {null
var n: Int? = null
n?.let {
// statement(s) will
// not execute as a is null
print(it)
}
// re-initializing value of a to 2
n = 5
n?.let {
// statement(s) will execute
// as a is not null
print(n)
}
}
Output
5
3:-run function
This type of scope function has this as a context object and lambda result as a result value. This scope function is use if you want to operate on nullable object, execute lambda expression on a nullable object and avoid NullPointerException.
Using run function
class SchoolDemo() {
lateinit var classname: String
lateinit var sunject: String
}
fun main(args: Array<String>) {
println("School Name : ")
var schoolDemo: SchoolDemo? = null
// body only executes if
// company is non-null
schoolDemo?.run {
print(classname)
}
print("School Name : ")
// re-initialize company
schoolDemo = SchoolDemo().apply {
classname = "Sixth"
sunject = "data structure"
}
// body executes as
// 'company' is non-null
schoolDemo?.run {
println(classname)
println(sunject)
}
}
Output
School Name : Sixth
data structure
4:-apply function
This type of scope function has this as a context object and context object as a result value. This scope function is use if you want to initiate or configuration an object.
Using apply function
class CLG() {
lateinit var classname: String
lateinit var sunject: String
}
fun main() {
CLG().apply {
classname = "Math class"
sunject = "Math 2nd"
}
}
5:-also function
This type of scope function has it as a context object and context object as a result value. This scope function is use if you want to do some additional object configuration or operation.
Using also function
fun main() {
// initialized
val list = mutableListOf<Int>(1, 2, 3)
// later if we want to perform
// multiple operations on this list
list.also {
it.add(4)
it.remove(2)
// more operations if needed
}
println(list)
}
Output
[1, 3, 4]
When to use which functions-
- with function :- if you want to operate on a non-null object.
- let function :-if you want to just execute lambda expression on a nullable object and avoid NullPointerException.
- run function :-if you want to operate on nullable object, execute lambda expression on a nullable object and avoid NullPointerException.
- apply function:-if you want to initiate or configuration an object.
- also function:-if you want to do some additional object configuration or operation.
Object References
We can reference object two types in scope functions:
- this
- it
This
By a lambda receiver keyword – this we can refer to the context object. this keyword is used in object reference in ‘run’, ‘with’, and ‘apply’ functions.
Company().apply {
this.name = “Codinglance”
this.founder = “Mohd Aasim”
}
It
‘let’ and ‘also’ used it keyword to refer to the object’s context as a lambda argument.
Company().let {
it.name = "Codinglance"
it.founder = "Mohd Aasim"
}
Return values
There are two types of return values in scope functions:
- Lambda result
- Context object
1:-Lambda result
Suppose we write any expression at the end of the code block then it would be the return value for the scope function. Scope function like ‘let’, ‘run’, and ‘with’ retrurn lambda result as return value.
class Company {
var name: String = "Codinglance"
var founder: String = “Mohd Aasim“
}
fun main() {
val founderName: String = with(Company()) {
// 'founder' is returned by 'with' function
founder
}
println(“Codinglance’s Founder : $founderName")
}
output
Codinglance’s Founder : Mohd Aasim
2:- Context object
Scope function like ‘apply’ and ‘also’ functions return the context object itself. Here we don’t need to specify the return value it will automatically returned.
Output:
Codinglance’s Founder: Mohd Aasim