函数
基本使用
Kotlin中函数使用关键字,函数名紧跟其后
//代码快函数体
fun add(a: Int, b: Int): Int {
return a + b;
}
//表达式函数体,支持类型推导可以省略return关键字
fun ad(a: Int, b:Int) = a + b;
//可以将lambda表达式存储在一个变量中
val add = { a: Int, b: Int -> a + b}
命名参数
命名参数指在调用函数时传入形参的名
fun showInfo(name: String, age: Int){
println("name:$name, age:$age")
}
showInfo("Tom", 18)
showInfo(name = "Tom", age = 18) //命名参数
默认参数
fun showInfo(name: String = "保密", age:Int = 0){
println("name:$name, age:$age")
}
showInfo()
showInfo(name = "Tom", age = 18)
可变参数
fun showInfo(vararg text: String){
text.forEach{ println(it) }
}
showInfo("hello", "android", "kotlin")
val list = arrayOf("hello", "world")
showInfo(*list);
数组转可变长参数
fun main(){
val arr = arrayOf("a", "b", "c")
myfun(*arr)
}
fun myfun(vararg args: String){
args.forEach{
println("- $it")
}
}
a
b
c
函数类型
- 函数类型就是函数的类型。变量可以有类型,函数也是可以有的,在kotlin中,函数时一等公民
- 函数类型指将函数的“参数类型”和“返回值类型”抽象出来
//函数类型为:(Int, Int) -> Float
fun add(a: Int, b: Int): Float { return (a + b).toFloat() }
说明:这个函数的参数类型是两个类型,返回值的类型是类型,所以函数类型是
高阶函数
- 高阶函数是将函数用作参数或返回值的函数
fun sum(x: Int): (Int) -> Int {
return { y: Int -> x + y }
}
//等价于
fun sum(x: Int) = { y: Int ->
x + y
}
val result = sum(1)(2) //结果:3
Lambda
定义
- Lambda可以理解为函数的简写
- Lambda表达式必须用包裹
- Lambda表达式声明了参数和返回值类型,那么Lambda变量可以省略类型声明
- 返回值为函数体的最后一行代码
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
SAM转换
- SAM是Single Abstract Method的缩写,意思是只有一个抽象方法的累或者接口。但在kotlin和java 8中,SAM表示只有一个抽象方法的接口
- 只要符合SAM要求的接口,编译器就能进行SAM转换,我们可以使用Lambda表达式简写接口类型的参数
- 当一个函数的参数是SAM的情况下,我们既可以用匿名内部类的方式传参,也可以用Lambda方式传参
//onClickListener是一个SAM接口
public void setOnclickListener(OnClickListener l){
}
//编译器会SAM转换为
fun setOnClickListener(object: View.OnClickListener) {
override fun onClick(v: View?){
println("hello world")
}
}
//可以传入Lambda表达式
button.setOnClickListener{ println("hello world") }
无参数
fun say(){
println("say hello")
}
//或简化为
val say = { println("say hello") }
有参数
fun sun(a: Int, b: Int): Int {
return a + b
}
//等价于
val sum:(Int, Int) -> Int = {a,b -> a+ b}
//等价于
val sum = {a: Int, b:Int -> a + b }
匿名函数
fun sum(a:Int, b:Int):Int{
return a + b
}
//等价于
val sum = fun(a:Int, b:Int): Int {
return a + b
}
自运行Lambda
val ret = {a:Int, b:Int -> a + b}(1,2) //结果:3
带接收者的函数类型
fun User.operate(hello:String, block:User.(String) -> Unit): User{
this.block(hello)
return this
}
fun main(){
val user = User("小名", 18)
user.operate("hello world"){
println("姓名:${this.name},年龄:${this.age}")
println(it)
}
}
//姓名:小明,年龄:18
//hello world
这个带接收者的函数类型,其中类型被称为接收者类型,被称为接收者对象;指接收者类型的对象,通过编译器注入的,是可以被省略的。
val sum: Int.(Int) -> Int = { other ->
this.plus(other)
}
3.sum(2)
sum(3, 2)
sum.invoke(3, 2)
闭包
一个函数内部申明或返回一个函数,那么这个函数称为闭包。
在Kotlin中,变量的作用域只有两种:全局变量和局部变量。
- 全局变量:函数内部和函数外部都可以直接访问。
- 局部变量:只有在函数内部可以方位。
闭包的设计就是为了能让开发者在函数外部访问函数内部的局部变量
fun main() {
val t = test() //1
t()//2
t()//3
}
fun test(): () -> Int {
var a = 1
println(a)
return fun(): Int {
a++
println(a)
return a
}
}
Kotlin实现接口回调
Java思想实现
interface ICallback {
fun onSuccess(msg: String)
fun onError(err: String)
}
class TestCallback {
private var mCallback: ICallback= null
fun setCallback(callback: ICallback) {
mCallback = callback
}
fun test() {
mCallback?.onSuccess("成功")
mCallback?.onError("失败")
}
}
fun main() {
val testCallback = TestCallback()
testCallback.setCallback(object : ICallback {
override fun onSuccess(msg: String) {
println(msg)
}
override fun onError(err: String) {
println(err)
}
})
testCallback.test()
}
Kotlin高阶函数思想实现
去掉了接口和匿名内部类
class TestCallback {
private var success: ((String) -> Unit)= null
private var error: ((String) -> Unit)= null
fun setCallback(success: ((String) -> Unit)?, error: ((String) -> Unit)?) {
this.success = success
this.error = error
}
fun test() {
success?.invoke("yes")
error?.invoke("no")
}
}
fun main() {
val testCallback = TestCallback()
testCallback.setCallback({ println(it) }, { println(it) })
testCallback.test()
}