代码之家  ›  专栏  ›  技术社区  ›  grooble

Kotlin中带有接收器的函数文本

  •  0
  • grooble  · 技术社区  · 7 年前

    我正在尝试使用Kotlin中的Receiver示例,基于本教程: https://kotlinexpertise.com/coping-with-kotlins-scope-functions/

    我希望从下面的代码中得到3,但似乎int方法dec()没有执行,或者“m int”变量没有更新。

    fun summer(block: Int.() -> Unit): Int{
         var myint = 5
        myint.block()
        return myint
        }
    fun main(args: Array<String>) {
        var mint = summer{
            dec()
            dec()
         }
        println(mint)
    }
    

    这里的输出是“5”。

    有人能就如何使这个“简单”的例子工作提出一些建议吗?

    4 回复  |  直到 7 年前
        1
  •  2
  •   s1m0nw1    7 年前

    本文作者。你的 summer 函数的 block 函数不返回任何内容,应将类型更改为 block: Int.() -> Int 然后返回其响应:

    fun summer(block: Int.() -> Int): Int {
        val myint = 5
        return myint.block()
    }
    

    现在,您打印的整数将是 4 因为最后一个 dec() 将成为传递的lambda的结果。为了解决这个问题,你可以用链子把两者都拴起来。 dec 电话:

    fun main(args: Array<String>) {
        val mint = summer {
            dec().dec()
        }
        println(mint)
    }
    

    最后, 5 将减量两次,导致 3 .

    另一方面,如果你有一个任意的对象,它被一个 12月 函数,您的方法如下所示:

    class Ref(var v: Int) {
        fun dec() {
            v -= 1
        }
    }
    
    fun summer(block: Ref.() -> Unit): Int {
        val ref = Ref(5).apply(block)
        return ref.v
    }
    
    fun main(args: Array<String>) {
        val mint = summer {
            dec()
            dec()
        }
        println(mint)
    } 
    
        2
  •  2
  •   Willi Mentzel user670265    7 年前

    inc() dec() 不要改变它们被调用的对象。相反,它们返回对象的一个变异副本:

    不起作用:

    var a = 5
    a.inc()
    println(a) // 5
    

    作品:

    var a = 5
    a = a.inc()
    println(a) // 6
    
        3
  •  1
  •   nPn    7 年前

    我认为这是因为dec()是一个运算符,不修改基础值。 例如,您运行此代码时,应该看到我从不更改,注意使用val而不是var,在您的示例中,您的想法应该是给您一个提示。 如果将int包装在一个类中,您可以看到带有接收器的函数是如何工作的。

    data class Foo(var i:Int) {
        fun dec() {
            i = i.dec()
        }
    }
    
    
    fun summer(block: Foo.() -> Unit): Foo{
        val myint = Foo(5)
        myint.block()
        return myint
    
    
    }
    
    fun main(args: Array<String>) {
    
        val i = 42
        println("i = $i")  // i = 42
        val j = i.dec()   
        println("j = $j")  // i = 41
        println("i = $i")  // i = 42
    
        val x = summer {
            dec()
            dec()
        }
        println(x)  // Foo(i=3)
    
    }
    
        4
  •  1
  •   zsmb13    7 年前

    您可以在文档中找到有关 operators :

    这个 inc() dec() 函数必须返回一个值,该值将分配给 ++ -- 已使用操作。他们不应该改变 inc dec 被调用。

    因此,本质上,使用如下运算符调用:

    x++
    y--
    

    会被翻译成 股份有限公司 / 12月 功能:

    x = x.inc()
    y = y.dec()
    

    额外发现:在这些函数或运算符上使用意图操作可以让您在两个表单之间进行转换,但这样做是错误的(更改行为,甚至可能破坏编译)。这里有一个问题有待解决。