访问外部价值内适用
简短的例子:
class MyClass { val someName = "want this value" val someOther = SomeOther().apply{ someName = someName } // other stuff below }
SomeOther
将它自己的someName
值应用到someName
,所以value应用没有什么区别(x = x)。
问:如何访问外部someName
( “想要这个值” )在里面apply
?
更新我有进一步的疑虑相关的建议使用this.someName=someName
,下面2代码片断,第一个按预期工作,令人惊讶的是第二个失败与类似的行为描述。
第一
fun main(args: Array) { class SomeOther { var someName: String? = null } val someName = "want this value" print(SomeOther().apply { this.someName = someName }.someName) // works! }
第二
class SomeOther { var someName: String? = null } class MyClass { val someName = "want this value" val someOther = SomeOther().apply { this.someName = someName } fun go() = print(someOther.someName) } fun main(args: Array) = MyClass().go() // prints null
问:区别在哪里?
你也可以使用also
function。 这相当于apply
,除了它将绑定你的对象而不是this
:
val someName = "want this value" val someOther = SomeOther().also { it.someName = someName }
also
function被添加到Kotlin 1.1,特别是当你不想从外部的范围中影响this
。
使用这个参考expression式如下:
val someOther = SomeOther().apply { someName = this@MyClass.someName } // reference to the outer class ---^
和 T.apply
函数是一个方便的方式来应用Builder设计模式 ,这样你永远不需要使用this
或额外的参数,例如:
val foo = Foo().apply { //v--- no need using `this` or any addition parameters foo = "bar" fuzz = "buzz" } class Foo { lateinit var foo: String; lateinit var fuzz: String }
编辑
你可以假设apply(lambda)
将应用一个匿名类Function2
实例,那么你知道为什么立即?
在你的第一个方法中,它看起来像下面这样:
val lambda: Function2 = { thisRef, arg -> thisRef.someName = arg; // ^--- parameter is used in lambda thisRef } val someName = lambda(SomeOther(), "want this value").someName println(someName)
在你的第二种方法,它看起来像下面这样:
class MyClass { val lambda: Function2 = { thisRef, arg -> // the parameter `arg` is never used in lambda ---^ thisRef.someName = thisRef.someName // ^--- it use thisRef's someName rather than arg's thisRef } val someOther = lambda(SomeOther(), this) }
尝试这个:
val someName = "want this value" val otherName = SomeOther().apply { this.someName = someName } // internal someName ---^ ^ // external someName ---^ print(otherName.someName) // >>> want this name