内部访问外部值适用

wil*_*ilu 4 kotlin

简短的例子:

class MyClass {
 val someName = "want this value"
 val someOther = SomeOther().apply{ someName = someName }
 // other stuff below
}
Run Code Online (Sandbox Code Playgroud)

SomeOther将应用其自己的值someNamesomeName,所以值应用没有差别(X = X).

问:如何在内部访问外部someName("想要此值")apply

更新 我对使用建议有进一步的怀疑this.someName=someName,低于2个代码片段,第一个按预期工作,令人惊讶的是第二个失败的行为与描述的相似.

第一

fun main(args: Array<String>) {
    class SomeOther {
        var someName: String? = null
    }
    val someName = "want this value"
    print(SomeOther().apply { this.someName = someName }.someName) // works!

}
Run Code Online (Sandbox Code Playgroud)

第二

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<String>) = MyClass().go() // prints null
Run Code Online (Sandbox Code Playgroud)

问:区别在哪里?

mar*_*ran 9

你可以使用also-function代替.它相当于apply,除了它将你的对象绑定到it而不是this:

val someName = "want this value"
val someOther = SomeOther().also { it.someName = someName }
Run Code Online (Sandbox Code Playgroud)

also当你不想this从外部范围遮蔽时,-function被特别添加到Kotlin 1.1中.


hol*_*ava 7

使用此引用表达式如下:

val someOther = SomeOther().apply { someName = this@MyClass.someName }
//                 reference to the outer class ---^
Run Code Online (Sandbox Code Playgroud)

并且T.apply函数是应用Builder Design Pattern的便捷方式,这样您根本不需要使用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
}
Run Code Online (Sandbox Code Playgroud)

编辑

你可以假设apply(lambda)哪些将应用匿名类的Function2<T,ARG,T>实例,然后你知道为什么立即?

在您的第一种方法中,它看起来如下所示:

val lambda: Function2<SomeOther, String, SomeOther> = { thisRef, arg ->
    thisRef.someName = arg;
    //                 ^--- parameter is used in lambda
    thisRef
}

val someName = lambda(SomeOther(), "want this value").someName

println(someName)
Run Code Online (Sandbox Code Playgroud)

在你的第二种方法中,它看起来如下:

class MyClass {
    val lambda: Function2<SomeOther, MyClass, SomeOther> = { 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)
}
Run Code Online (Sandbox Code Playgroud)