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

You may also like...

0 Comments

No Comment.