【问题标题】:如何在 Kotlin 中将对象表达式转换为 lambda? [复制]
【发布时间】:2022-01-23 13:10:04
【问题描述】:

我是 Android 开发的新手。最近我正在学习 Kotlin,我正在尝试找出 setOnClickListener。但是,我在使用 Kotlin 将对象表达式转换为 lambda 的过程中遇到了一个问题。

步骤 1. Java 中的 setOnClickListener:

buttonLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // my code
            }
        });

第 2 步。然后我使用对象表达式将 Java 代码转换为 Kotlin 代码:

buttonLogin.setOnClickListener(object : View.OnClickListener {
            override fun onClick(p0: View?) {
                // my code
            }
        })

第 3 步,然后 IntelliJ 提示我将对象表达式转换为 lambda:

buttonLogin.setOnClickListener {
        // my code
    }

它看起来更简洁,但是,我无法理解第 3 步背后的逻辑。 于是上网查了一些资料,上面写着

任何接收具有单个函数的接口的函数都可以 替换为 lambda

它在 setOnClickListener 上起作用。 但是我还是不能完全理解,所以我定义了一个接口和类来验证一下。

这是我的代码:

interface MyInterface {
    fun method1()
}

class MyClass {
    fun method2(myInterface: MyInterface) {
        myInterface.method1()
    }
}

fun main() {
    val myClass = MyClass()
    myClass.method2(object : MyInterface {
        override fun method1() {
            println("Hello, world.")
        }
    })
    
    // So how to write the lambda to replace object expression?
}

【问题讨论】:

    标签: android kotlin lambda


    【解决方案1】:

    第 3 步中的代码称为尾随 lambdas

    根据 Kotlin 约定,如果函数的最后一个参数是函数,那么作为相应参数传递的 lambda 表达式可以放在括号外,

    如果 lambda 是该调用中的唯一参数,则可以完全省略括号:

    例如:

    fun function(f : (String) -> Unit) {
    
    }
    
    fun main() {
        function {
            
        }
    }
    

    查看 Kotlin 文档了解此功能

    https://kotlinlang.org/docs/lambdas.html#passing-trailing-lambdas

    您可以转换您的代码以使用此功能

    class MyClass {
        fun method2(function: () -> Unit) {
            function()
        }
    }
    
    fun main() {
        val myClass = MyClass()
        myClass.method2 {
            println("Hello, world.")
        }
    
        // Or you can store the lambda in variable and use it like tihs
        val myClass2 = MyClass()
        val function = {
            println("Hello, world.")
        }
        myClass2.method2(function)
    
    }
    

    或者只是将您的界面转换为功能界面

    fun interface MyInterface {
        fun method1()
    }
    
    class MyClass {
        fun method2(myInterface: MyInterface) {
            myInterface.method1()
        }
    }
    
    fun main() {
        val myClass = MyClass()
        myClass.method2 { 
            println("Hello, world.") 
        }
    }
    

    【讨论】:

    • 您好,先生。您能帮我使用 lambda(即 MyClass.method2)完成我的代码吗?
    • 当然,我已经用新代码更新了我的答案
    • 先生,感谢您的快速回复。所以,如果我想将对象表达式转换为 lambda,我需要像上面写的那样重新定义 MyClass.method2。那是对的吗?回到setOnClickListener,为什么IntelliJ不用重新定义setOnClickListener方法就可以将对象表达式转成lambda?
    • 是的兄弟,我已经添加了另一个答案,对于你的最后一个问题,Kotlin 如何转换它,它真的没有重新定义它,但 OnClickListener 是一个功能接口,它是一个只有一个功能的接口,所以Kotlin 中的这种语法糖,在答案中我在 Kotlin 中添加了示例
    • 你刚刚救了我的命!这个问题困扰了我好几天。我没有意识到 Kotlin 中的函数式接口需要以 fun 为前缀。这就是为什么我无法通过编译器。再次感谢您耐心的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 2013-03-06
    相关资源
    最近更新 更多