Home > OS >  Is there a use for the "with" function that I can't achieve by "apply", &qu
Is there a use for the "with" function that I can't achieve by "apply", &qu

Time:11-18

When would we ever need with in Kotlin if we can already use apply, run, also and let?

Can anyone give me a clear example?

CodePudding user response:

In most situations, a with call can be transformed to a run like this:

with(foo) {
    // some code ...
}

// is the same as:

foo.run {
    // the same code ...
}

run and with will both return the lambda result, and will use foo as the lambda receiver.

However, I can think of one case where this wouldn't work - when foo declares its own run method that takes a lambda, e.g.

// having something like this isn't too uncommon, right?
fun run(x: () -> Unit) {}

The lambda type doesn't have to be exactly the same as the scope function run. Any function type should work. Then overload resolution wouldn't resolve to the built-in run.

You can force the resolution by doing some casts, but using with in this case is much better. Don't you agree?

CodePudding user response:

I don’t think there’s any better example than with(context). Maybe it’s not clear if English isn’t one of your primary languages, but it semantically is translated into English much clearer than context.run when the object is being used to produce a result but isn’t the primary actor, so it makes code a little easier to read.

This of course raises the question of why run exists. Well, it semantically makes more sense in English when the object is the thing doing the action. In English, the context of an action is what you’re doing something with. But if the object is what is directly producing the result, then it is running the action.

Also, you can’t do ?.with.

CodePudding user response:

While the basic usage of all of them is same but there are some differences between let, apply, run and with keywords in kotlin. As you can see in this example:

enter image description here

Now let's see some differences:

  1. See that here, intent object is nullable. when the receiver object is null - let, apply and run don't recognize the property flags while with doesn't have a problem.

enter image description here

  1. Now another difference is in the result when using these keywords.

For example, apply keyword:

The apply function is invoked on a receiver T, and the receiver T also becomes the result of apply automatically.

//returns receiver T, T exposed as `this`
fun <T> T.apply(block: T.() -> Unit): T 

And with keyword, The with function, as opposed to all other scope functions (let, run, apply), is not defined as an extension function. Instead, the function is invoked with a receiver object as its first argument explicitly. The result is the last statement.

//return arbitrary value R, not an extension function, T exposed as this fun <T, R> with(receiver: T, block: T.() -> R): R

Example:

val result = with(Intent()) {
            flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
            "RESULE"
        }
        
        val result2 = this.apply {
            actionBar?.title = "abc"
            templateViewModel = TemplateViewModel(repository = ProductRepository(null))
        }

result is a string, and result2 is TemplateActivity

  • Related