kotlin(六)--匿名函数
匿名函数
-
匿名函数和普通函数没有什么区别,只是没有名字而已
-
如果是单表达式的函数体,可以用赋值运算符代替大括号,而且可以省略返回值类型,编译器可以推断是否有返回值,如果有类型是什么类型。这个其实和匿名函数没有关系,普通函数也能用
-
如果编译器可以推断出匿名函数的形参类型,可以将形参类型省略
-
匿名函数是可以作为函数参数的,在实际使用中函数的参数类型是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() }
上一篇: kotlin基础(四)----扩展
下一篇: 安卓7.0以后打开本地文件方式