Harsh Shah
Harsh Shah

Reputation: 2362

Kotlin: difference between IT and THIS keyword

In one of the kotlin interviews, someone asked me the difference between it & this keywords.

I have a search on google but unable to find a proper answer for the question.

Can someone guide me what's the actual difference between these two?

I know this is very basic question, I am a novice in the kotlin.

Upvotes: 40

Views: 18905

Answers (6)

Ara Mkrtchyan
Ara Mkrtchyan

Reputation: 507

If you take a look at kotlin scope functions doc:

https://kotlinlang.org/docs/scope-functions.html

Some of them have "this" in their scopes and others use "it". The difference is the following:

this: When you use scope functions that use "this", f.i. apply {} it changes the context of function's scope to the context of an object on which this function was called, e.g.:

//Outer context in outer scope

val alice = Person("Alice").apply {

//Person object's context in function's inner scope

this.age = 20   //"this" refers to the object's context 
city = "London" //you can skip writing "this" because you are in the context of object
}

it: When you use functions that use "it", f.i. also {} it DOES NOT change the context of function's scope, so it remains the same as the context where the function was called, e.g.:

//Outer context in outer scope

val alice = Person("Alice").also {

//Same outer context in function's inner scope

it.age = 20        //"it" refers to the object's reference holder e.g. alice
it.city = "London" //you can not skip writing "it" because you are in outer context
}

NOTE: The context and the scope are 2 different things. In both cases the scope is changed so that if you declare a local variable within that scope it will not be visible from outer scope, and in 1 case the context changes and in the other one it remains the same and hence the usage of "this" and "it".

Upvotes: 2

NehaK
NehaK

Reputation: 2737

If this helps some one :

With scope like : run, apply, with, to call the methods of the object, we can call them directly as it has scope of the object. In another words run-block has "this" scope.

private fun methodWithRun() {

    val dummy = Dummy()
    dummy.run {
        this.dummyFun()
        this.dummyVar = "10"
    }
    
}

While scope like : let, also, to call the methods of the object, we can call them using the "it" as it has scope of the class win which this method is written.

private fun methodWithLet() {
    
    val dummy = Dummy()
    dummy.let {
        it.dummyFun()
        it.dummyVar = "10";
    }
    
}

Upvotes: 2

Saeed Entezari
Saeed Entezari

Reputation: 3755

You need to know about Scope Functions:

The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope.

Inside this scope there is a Context object either as this or it

In Scope functions run, apply and with the scope is (temporarily) changed to the scope of the object you are calling this function on:

val str = "Hello"
str.run {
    //Here this refers to str
}

In Scope functions let, also the scope is not changed (remains the same as caller scope) but your lambda will receive the context as it inside the lambda:

val str = "Hello"
str.let {
    //Here it refers to str
}

You can check the links for more information.

Upvotes: 18

Tenfour04
Tenfour04

Reputation: 93882

it is only relevant inside a lambda with a single parameter. It is the default name for a single parameter and is a shorthand that allows you to omit naming the single parameter. A function that is declared this way might look like this:

(String) -> Unit

In a lambda, this is the receiver argument. It only works if the function is defined as having a receiver, like this:

String.() -> Unit

If the function declaration does not have a receiver, this has the same meaning it does outside the scope of the lambda. For an extension function, that’s the receiver of the extension function. Otherwise, it’s the class containing the function.

Upvotes: 23

USMAN osman
USMAN osman

Reputation: 1030

I would like to go extreme fundamental with no fancy words.

it keyword
When you have one parameter you can call using it keyword and it works so good with HOF, for instance,

 private fun itKeyword(itKeyword:(String) -> Unit) {
        itKeyword("")
    }

    fun callItFun() {
        itKeyword {//it:String // this is high light over here like this

        }

But if you try to do something like this:

private fun itKeyword(itKeyword:(String, Int) -> Unit) {
        itKeyword("", 1)
    }

    fun callItFun() {
        itKeyword {yourName, age -> //yourName, age is define by user
        }
   }

see? there is no it keyword define over here by compiler but instead we have to pass two parameters when we defined HOF but if we keep this empty, compiler will give us error Hey pass something dude, i don't what variable you are talking about there are two variables passed over here.
That means, when you have only one parameter you can call it by using it keyword.

this keyword
there are two scope or variables/properties global and local scope, when you have defined some variable as a global scope and you wanna call it in multiple methods/functions and at some place you have to use same type of another variable with the same name at local scope, in that case we will be using this keyword and why is that so?

private lateinit var mContext: Context

    fun thisKeyword(mContext: Context) {
        this.mContext = mContext
    }

but what if we don't use this keyword and keep it like this:

private lateinit var mContext: Context
    fun thisKeyword(mContext: Context) {
        mContext = mContext
    }

Compiler would say, mah man what have you done, didn't ring a bell in my head JK, Compiler would say, Val cannot be reassigned, wait what? we didn't init it as a val but if we see at global scope we have init it as var but guess what? compile is right. In Kotlin when pass something into functions parameter they act as a Val by default which means without this compiler was using local scope variables not global scope but when we use this keyword we tell compiler, with keyword this property over here before = is global scope this.mContext and after = is local one so this is the reason we use this keyword to refrains from variable conflict.

i hope this helps, thankYou().

Upvotes: 1

Jeel Vankhede
Jeel Vankhede

Reputation: 12138

Difference between it & this keywords can be explained by taking example of lambda method receivers (a.k.a higher order functions).

Let's say you've written a function or using a function which provides you callback as lambda method receiver. Something like this: () -> Unit

So, there are two possibilities how you want your callback to be:

  1. Providing parameter to callback

    • Parameter by callback means you want to give your callback a parameter that caller can use on the time of invocation, also considered as it.

Whatever written above simply means: (Int) -> Unit. this functional method parameter can give you integer at the time of invocation.

Check out the snippet below:

fun someMethodWithCallback(callback: (Int) -> Unit) {
    callback(0)
}

// On the time of consumption, the `Int` parameter by default exposed to callback as it parameter.
obj.someMethodWithCallback { it -> // Here it is the method parameter of callback that we passed, you can also rename it to any other named value
    // it can be directly used as Int value if needed or you can rename it at receiver above
}

Note: You can provide multiple parameters to callback and then you won't be able to receive it, rather callback would provide you number of variables passed instead.

  1. Providing object to callback

    • Another way to provide callback is by providing object itself as callback parameter. Which means that callback syntax slightly changes and gives you object itself as callback parameter this.

Whatever written above simply means: Int.() -> Unit. this functional method object can give you integer at the time of invocation.

Check out the snippet below:

fun someMethodWithCallback(callback: Int.() -> Unit) {
    callback(0)
}

// On the time of consumption, the `Int` parameter by default exposed to callback as it parameter.
obj.someMethodWithCallback { this // Here this is the method object of callback that we passed, you can not rename it to anything else
    // it can be used as Int value by referencing as this
}

Hope it make sense!

Upvotes: 7

Related Questions