欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

kotlin(六)--匿名函数

程序员文章站 2022-04-15 18:44:07
...

匿名函数

  1. 匿名函数和普通函数没有什么区别,只是没有名字而已

  2. 如果是单表达式的函数体,可以用赋值运算符代替大括号,而且可以省略返回值类型,编译器可以推断是否有返回值,如果有类型是什么类型。这个其实和匿名函数没有关系,普通函数也能用

  3. 如果编译器可以推断出匿名函数的形参类型,可以将形参类型省略

  4. 匿名函数是可以作为函数参数的,在实际使用中函数的参数类型是lambda函数类型,可是穿个匿名函数是没问题的,这也能说明lambda的底层实现是匿名函数,比如filter方法

    //普通函数
    fun add(x:Int,y:Int):Int{
       
    }
    
    //匿名函数
    var add = fun(x:Int,y:Int):Int{
        return x+y
    }
    
    // 匿名函数单表达式函数体简写
    var add = fun(x:Int,y:Int) = x+y
    
    

lambda表达式

lambda是对匿名函数进一步简化

在kotlin语言中,对类型这个概念进一步抽象了,类,基本类型都是类型,匿名函数也能抽象出类型,叫做函数类型,而且类型在kotlin中是放在变量名+冒号(:)后面的,函数类型就需要和lambda表达式一块使用了。

var add1 :(Int,Int)->Int = {a,b->a+b}

//进一步简化

var add2 = {a:Int,b:Int->a+b}

(Int, Int) -> Int 这个叫函数类型,add1叫函数类型的变量,{a, b -> a + b}是变量的值。这里大家不要混淆了,本质上这个还是函数,只是使用lambda语法简化了,要想使用函数还是得调用才行呀!

既然函数可以抽象成一个类型,那么函数类型就可以作为方法的参数传,这样的话就给编程带来极大的灵活性

fun test(a:Int,b:(Int,Int)->Int):Int{
    return a+b(2,3)
}

//调用
//相加
var result = test(1,{num1,num2->num1+num2})

//相乘
var result1 = test(1,{num1,num2->num1*num2})

上面的调用会有提示: Lambda argument should be moved out of parentheses,这个意思就是说,需要把lambda表达式移到括号外面 。这是因为,如果lambda是函数最后一个表达式,它可以写道外面

var result = test(1){num1,num2->num1+num2}

虽然lambda表达式的底层式匿名函数,可是还是有不一样的地方。

匿名函数的本质依旧是函数,因此匿名函数的return则用于返回该函数本身。
Lambda表达式的return用于返回它所在的函数,而不是返回Lambda表达式。

还有一个概念是函数字面值(量),其实就是指一个函数体,或者说是一段代码,本身没有名字,我们可以把它绑定到一个变量上,通过这个变量操作它,lambda表达式和匿名函数都叫函数字面值。

我们在java中定义一些工具类方法的时候,我们一般把这类方法定义成类方法。在kotlin中就不用这样干了,直接在文件中定义方法就行,不用类包裹了,不过编译器最后还是把它编译成了类方法。

总结一下

1. 无参数的情况 :
	val/var 变量名 = { 操作的代码 }
	
2. 有参数的情况
	val/var 变量名 : (参数的类型,参数类型,...) -> 返回值类型 = {参数1,参数2,... -> 操作参数的代码 }可等价于// 
	此种写法:即表达式的返回值类型会根据操作的代码自推导出来。
	val/var 变量名 = { 参数1 : 类型,参数2 : 类型, ... -> 操作参数的代码 }
	
3. lambda表达式作为函数中的参数的时候,这里举一个例子:
fun test(a : Int, 参数名 : (参数1 : 类型,参数2 : 类型, ... ) -> 表达式返回类型){ ... }



lambda表达式总是被大括号括着。

定义完整的Lambda表达式如上面实例中的语法2,它有其完整的参数类型标注,与表达式返回值。当我们把一些类型标注省略的情况下,就如上面实例中的语法2的另外一种类型。当它推断出的返回值类型不为'Unit'时,它的返回值即为->符号后面代码的最后一个(或只有一个)表达式的类型。
  
 在上面例子中语法3的情况表示为:高阶函数,当Lambda表达式作为其一个参数时,只为其表达式提供了参数类型与返回类型,所以,我们在调用此高阶函数的时候我们要为该Lambda表达式写出它的具体实现。

枕风宿雪经复年


实例

Android开发中为RecyclerView的适配器编写一个Item点击事件

class TestAdapter(val context : Context , val data: MutableList<String>)    : RecyclerView.Adapter<TestAdapter.TestViewHolder>() {    
    private var mListener : ((Int , String) > Unit)? = null
    
    override fun onBindViewHolder(holder: TestViewHolder?, position: Int) {              
        holder?.itemView?.setOnClickListener{ 
                mListener?.invoke(position, data[position])        
            }   
    }    
    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): TestViewHolder {        
         return TestViewHolder(View.inflate(context,layoutId,parent))   
     }   
    override fun getItemCount(): Int {        
        return data.size    
    }    
    fun setOnItemClickListener(mListener : (position : Int, item : String) -> Unit){        
        this.mListener = mListener    
    } 

    inner class TestViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
}
// 调用
TestAdapter(this,dataList).setOnItemClickListener { position, item ->        Toast.makeText(this,"$position \t $item",Toast.LENGTH_SHORT).show()    }


相关标签: 安卓 安卓开发