内部访问外部值适用

时间:2017-07-06 11:10:48

标签: kotlin

简短示例:

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

SomeOther会将自己someName的值应用于someName,因此值应用程序没有区别(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!

}

第二

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

问:区别在哪里?

4 个答案:

答案 0 :(得分:7)

您可以使用also - 函数代替。它等同于apply,但它会将您的对象绑定到it而不是this

val someName = "want this value"
val someOther = SomeOther().also { it.someName = someName }

当您不希望从外部范围隐藏also时,{K}专门添加了this - 函数。

答案 1 :(得分:5)

使用this reference expression,如下所示:

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

AND 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
}

修改

您可以假设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)

在你的第二种方法中,如下所示:

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)
}

答案 2 :(得分:1)

试试这个:

val someName = "want this value"
val otherName = SomeOther().apply { this.someName = someName }
//                     internal someName ---^          ^
//                                external someName ---^

print(otherName.someName) // >>> want this name

答案 3 :(得分:0)

您可以像这样访问退出申请

class SomeOther {
    var someName: String? = null
}

class MyClass {
    val someName = "want this value"
    val someOther = SomeOther().apply { this.someName = this@SomeOther.someName }
    fun go() = print(someOther.someName)
}