### lambda 有什么作用
Lambda 表达式是一种很简单的方法定义一个 匿名函数,避免写一些函数的抽象类或接口,然后在类中实现他们,Kotlin中函数可以作为另一个函数的参数。
### 都有那些使用场景
View.setOnClickListener() 方法。使用Java 的方式增加点击事件。
public interface OnClickListener {
void onClick(View v);
}
//编写一个匿名内部类去实现这个接口
view.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
}
});
转为kotlin
view.setOnClickListener(object : OnClickListener {
override fun onClick(v: View) {
toast("Click")
}
}
lambda表达式的参数在 箭头的左边,箭头的右边 是表达式的返回值。
view.setOnClickListener({ view -> toast("Click")})
//或者
view.setOnClickListener({ toast("Click") })
### Lambda语法
库函数 maxBy 可以在任何集合上调用,花括号中的代码 { it.age } 就是实现了这个逻辑的
Lambda 表达式
data class Person(val name: String, val age: Int)
fun main(args: Array<String>) {
val people = listOf(Person("yy", 24), Person("uu", 22))
println(people.maxBy { it.age }) //Person(name=yy, age=24)
}
最原始的语法声明应该是这样的,用括号包裹着 Lambda 表达式
println(people.maxBy({ p: Person -> p.age }))
Kotlin中 Lambda 表达式是函数调用的最后一个实参,可以将之放到括号的外边:
println(people.maxBy() { p: Person -> p.age })
当 Lamdba 表达式是函数唯一的实参时,可以去掉调用代码中的空括号对:
println(people.maxBy { p: Person -> p.age })
若当前上下文期待的是只有一个参数的 Lambda 表达式且参数类型可以被推断出来,
就会为该参数生成一个默认名称:it
println(people.maxBy { it.age })
### 作用域中访问变量
在 Kotlin 中函数内部的 Lambda 表达式不会仅限于访问函数的参数以及 final 变量,在 Lambda 内部也可以访问并修改非 final 变量,从 Lambda 内部访问外部变量,我们称这些变量被 Lambda 捕捉。当捕捉 final 变量时,变量值和使用这个值的 Lambda 代码一起存储,对非 final 变量来说,其值被封装在一个特殊的包装器中,对这个包装器的引用会和 Lambda 代码一起存储
var number = 0
val list = listOf(10, 20, 30, 40)
list.forEach {
if (it > 20) {
number++
}
}
println(number) //2
### 成员引用
成员引用用于创建一个调用单个方法或者访问单个属性的函数值,通过双冒号把类名称和要引用的成员(一个方法或者一个属性)名称分隔开。
主要用途:要当做参数传递的代码块已经被定义成了函数,此时不必专门创建一个调用该函数的 Lambda 表达式,可以直接通过成员引用的方式来传递该函数(也可以传递属性),成员引用对扩展函数一样适用
data class Person(val name: String, val age: Int) {
val myAge = age
fun getPersonAge() = age
}
fun Person.filterAge() = age
fun main(args: Array<String>) {
val people = listOf(Person("yy", 24), Person("uu", 22))
println(people.maxBy { it.age }) //Person(name=yy, age=24)
println(people.maxBy(Person::age)) //Person(name=yy, age=24)
println(people.maxBy(Person::myAge)) //Person(name=yy, age=24)
println(people.maxBy(Person::getPersonAge)) //Person(name=yy, age=24)
println(people.maxBy(Person::filterAge)) //Person(name=yy, age=24)
}
不管引用的是函数还是属性,都不要在成员引用的名称后面加括号
fun test() {
println("test")
}
fun main(args: Array<String>) {
val t = ::test
}
可以用构造方法引用存储或者延期执行创建类实例的动作
data class Person(val name: String, val age: Int)
fun main(args: Array<String>) {
val createPerson = ::Person
val person = createPerson("yyy", 24)
println(person)
}