一段代码封装成 匿名函数
完整语法说明: 函数类型 -> Lambda表达式
函数类型:(Int, Int) -> Int
lambda表达式: {x: Int, y: Int -> x + y}
完整Lambda表达式说明:{参数1:参数类型,参数2: 参数类型 -> 函数体}
val/var 变量名 = { 操作的代码 }
val test = { println("无参数") }
val/var 变量名 : (参数的类型,参数类型,...) -> 返回值类型
= {参数1,参数2,... -> 操作参数的代码 }
val sum: (Int, Int) -> Int = {x, y -> x + y}
val/var 变量名 = { 参数1 : 类型,参数2 : 类型, ... ->
操作参数的代码 }
val sum={x:Int, y:Int -> x+y}
fun test(a : Int, 参数名 : (参数1 : 类型,参数2 : 类型, ... )
-> 表达式返回类型){
...
}
fun test(a : Int , b : (num1 : Int , num2 : Int) -> Int) : Int{
return a + b.invoke(3,5)
}
函数变量的类型统称函数类型,函数类型就是声明该函数的参数类型列表和函数返回值类型
函数类型语法:(参数)->返回值类型
//无参、无返回值的函数类型(Unit 返回类型不可省略)
() -> Unit
//接收T类型参数、无返回值的函数类型
(T) -> Unit
//接收T类型和A类型参数、无返回值的函数类型(多个参数同理)
(T,A) -> Unit
//接收T类型参数,并且返回R类型值的函数类型
(T) -> R
//接收T类型和A类型参数、并且返回R类型值的函数类型(多个参数同理)
(T,A) -> R
(T,(A,B) -> C) -> R
1、fun 在没有等号、只有花括号的情况下,就是代码块函数体,如果返回值非 Unit,必须带 return
fun foo(x: Int) {
print(x)
}
fun foo(x: Int, y: Int): Int {
return x + y
}
2、fun 带有等号,没有花括号,是单表达式函数体,可以省略 return
fun foo(x: Int, y: Int) = x + y
3、不管是用 val 还是 fun 声明,如果是等号加花括号的语法,就是声明一个 lambda 表达式
val foo = { x: Int, y: Int ->
x + y
}
// 调用方式: foo.invoke(1, 2) 或者 foo(1, 2)
fun foo(x: Int) = { y: Int ->
x + y
}
// 调用方式: foo(1).invoke(2) 或者 foo(1)(2)
4、lambda 表达式自调用
{x: Int, y: Int -> x + y}(1, 2)
示例1:遍历集合
// 这里举例一个语言自带的一个高阶函数filter,
//此函数的作用是过滤掉不满足条件的值。
val arr = arrayOf(1,3,5,7,9)
// 过滤掉数组中元素小于5的元素,取其第一个打印。
// 这里的it就表示每一个元素。
println(arr.filter { it < 5 }.component1())
示例2:
fun test(num1 : Int, bool : (Int) -> Boolean) : Int{
return if (bool(num1)){ num1 } else 0
}
println(test(10,{it > 5}))
println(test(4,{it > 5}))
Lambda表达式中,可以用下划线(_)表示未使用的参数,表示不处理这个参数
val map = mapOf("key1" to "value1","key2" to "value2","key3" to "value3")
map.forEach{
key , value -> println("$key \t $value")
}
// 不需要key的时候
map.forEach{
_ , value -> println("$value")
}
指定的接受者对象调用Lambda表达式的功能
要用Lambda表达式作为接收者类型的前提是接收者类型可以从上下文中推断出来
class HTML {
fun body() {
println("HTML.body() >>>")
}
fun go(){
println("HTML.go() >>>")
}
}
fun html(init:HTML.()->Unit):HTML{
val html=HTML()// 创建接收者对象
html.init()// 将该接收者对象传给该 lambda
return html
}
//调用
html { body() }
html { go() } // 调用该接收者对象的一个方法
实战: 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()
}