Home > Software engineering >  How can I convert a `with` code to a full code in Kotlin?
How can I convert a `with` code to a full code in Kotlin?

Time:08-03

The Code A is from the article.

It' wrapped with with, I hope to convert it to a full code, how can I do?

BTW, Code B is wrong.

Code A

val pxValue = with(LocalDensity.current) { 16.dp.toPx() }

Code B

val s = LocalDensity.current
val pxValue=s.16.dp.toPx()

Add Content:

For example, the Code C is using with, I can write a full Code D instead of Code C without with.

Code C

data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Kotlin")

with(person) {
    name = "No Name"
    tutorial = "Kotlin tutorials"
}

Code D

data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Kotlin")

person.name = "No Name"
person.tutorial = "Kotlin tutorials"

CodePudding user response:

Why can you rewrite Code C into Code D, but not Code A into Code B? The difference, as the answer your linked also mentioned, is that toPx in Code A is an extension method of Dp declared in Density. It is declared like this:

open fun Dp.toPx(): Float

On the other hand, none of the properties you use in the with block in Code C are extension properties declared in Person.

So to call toPx, not only do you need an instance of Density as the dispatch receiver, you also need an instance of Dp as the extension receiver. (See this for more info about dispatch vs extension receivers)

With scope functions that change what the implicit receiver this means (e.g. with/run), you can easily provide both of these receivers:

with(LocalDensity.current) {  // LocalDensity.current: (implicit) dispatch receiver
    16.dp.toPx() // 16.dp: explicit extension receiver
}

It is possible (but not very intuitive or convenient) to provide both receivers without using scope functions. For example, and for academic purposes only, you can declare additional extension functions on Density:

fun Density.dpToPx(x: Int) = x.dp.toPx()
fun Density.dpToPx(x: Float) = x.dp.toPx()
fun Density.dpToPx(x: Double) = x.dp.toPx()

Here the dispatch receiver of x.dp.toPx is the same as the extension receiver of the newly declared Density.toPx, and the extension receiver is x.dp.

Then you can call this like this:

LocalDensity.current.dpToPx(16)

I strongly recommend you to use with when writing real code.

  • Related