代码A来自article.

它是用with包起来的,我希望把它转换成完整的代码,我该怎么办?

顺便说一句,代码B是错误的.

Code A

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

Code B

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

Add Content:

例如,代码C使用with,,我可以写一个完整的代码D,而不是没有with的代码C.

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"

推荐答案

为什么可以将代码C重写为代码D,而不能将代码A重写为代码B?正如您链接的答案所述,不同之处在于代码A中的toPx是在Density中声明的Dp中的extension方法.它是这样宣布的:

open fun Dp.toPx(): Float

另一方面,在代码C中的with块中使用的属性都不是在Person中声明的扩展属性.

因此,要调用toPx,您不仅需要Density的实例作为dispatch receiver,还需要Dp的实例作为extension receiver.(有关派单与分机接收器的详细信息,请参阅this)

通过改变隐式接收器this的含义的作用域函数(例如with/run),您可以轻松地提供这两个接收器:

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

在不使用作用域功能的情况下提供两个接收器是可能的(但不是非常直观或方便).例如,仅出于学术目的,您可以在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()

这里,调度接收器x.dp.toPx与新声明的Density.toPx的扩展接收器相同,而扩展接收器是x.dp.

那么你可以这样称呼它:

LocalDensity.current.dpToPx(16)

我强烈建议您在编写真正的代码时使用with.

Kotlin相关问答推荐

在Kotlin中将String转换为T

kotlin短路列表判断吗?

为何Kotlin标准库中的AND和OR函数不能像&&和||一样进行短路运算?

Kotlin SIZE_BYTES

协程子作业(job)取消

在 Kotlin 协程中切换 IO 和 UI 的正确方法是什么?

Kotlin 中获取类简单名称的最佳实践

如何在 Kotlin 中使用具有继承的泛型

如何为 material.Slider 视图创建绑定适配器?

java - 如何将函数作为参数从java传递给kotlin方法?

Kotlin 解构超过五个组件

将ExpectedException与Kotlin一起使用

如何在协程之外获取 Flow 的值?

使用范围的稀疏sparse值列表

如何在Kotlin中获得KType?

不推荐使用仅限生命周期的LifecycleEvent

通过在 kotlin-gradle 中使用子项目Unresolved reference: implementation

lateinit 的 isInitialized 属性在伴随对象中不起作用

java.lang.NoClassDefFoundError:解析失败:Lkotlin/time/MonoClock

如何在 Kotlin 中定义新的运算符?