Kotlin学历之函数与Lambda表达式
简述
类和对象的内容基本学完了,接下来将深入研究下Kotlin中的函数,与java相比,Kolin中的函数相对灵活很多,像命名参数语法,局部函数,高阶函数,尾递归函数等都会带来新的函数特性,用起来也是方便的很。本文主要研究函数和lambda表达式的常见语法及规则,后期将对高阶函数展开学习,下面开始基础讲解。
函数声明
fun 函数名(参数名:参数类型,参数名:参数类型):返回值类型{
return 返回值
}
这里的“:”很有意思,简单比对一下就忽然明白了为啥这么写了,看下面
数名:参数类型
函数名():返回值类型
对象名:父类、接口
//现在明白了吗,格式统一,“:”左边就相当于类的实现:对象,右边就是它的类。
函数调用方式
demo(1)
Sample.demo(1)
// 调用方式和java一样 但有一种调用方式不同 叫中辍调用
中辍表示法有如下特点:
是成员函数或扩展函数
**只有一个参数
**用infix关键字标注
例如:
infix fun Int.shl(x:Int) :Int{……}
//调用方式
1 shl 2 // 可以这么调用
1.shl(2) //正常写法
参数声明规则
格式是 name:_type,_参数用逗号隔开,每个参数必须有显式类型
默认参数
函数参数可以有默认值,当省略相应的参数时使用默认值。与其他语言相比,这可以减少重载数量
例1:
fun read(b :Array, off: Int= 0, len :Int = b.size()) {
…… // off 默认值0,len 的默认是是b 集合大小
}
例2:
//当覆盖一个带有默认参数值的方法时,必须省略默认参数值
override fun read(b :Array, off: Int, len :Int)
命名参数语法
这个目前看来是最重要的一个点,与java相比比较特殊,可以省去很对重载
例如在java中你定义这么几个函数
public void add(int a)
public void add(int a, String b)
public void add(int a, String b, boolean c)
public void add(int a, boolean c)
而在kotlin中只需要这样一行
fun add(a :Int , b :String ="bb",c :Boolean =false)
在使用过程中就可以这样使用
add (1)
add (1, "c")
add (1, "c",true )
//更可以这样 利用参数名直接用“=”号赋值
add ( a= 3, c = true)
Unit函数
unit 就相当于java中的void 一个意思,自己脑补吧不举例了,哈哈
单表达式函数
在kotlin中的函数是可以直接 用“=”号 代替大括号的函数体
例如:
fun double(x:Int):Int= x * 2
// 返回值类型也是可以省去
fun double(x:Int)= x * 2 // 这里是一个参数 可以推断出类型 所以可以省去,如果多个参数时,推断不出来就不可以省去了
可变数量参数
在java中 会用到“...” 来表示可变参数,在kotlin中则要使用Varargs 关键字修饰
例如:
fun add( vararg a : Int){
}
//这样就可以这么调用了add ( 1,2,4,5,6,3,1)
可变参数还有个“*”操作符直接将一个同等类型的参数传递进来
例如:
var arraya = arrayOf(1,2,3,4,5,6)
var arrayb= add( 2,6,7,89, *arraya) //这样就传进来了a的参数
成员函数
成员函数是在类或对象内部定义的函数,与java 一样,没什么特殊的
局部函数
局部函数就像java中的局部变量一样,在函数体里面的函数就是局部函数
例如:其实说白了就相当于在java 函数内部调用外部函数,只是说函数定义在 函数内部。
fun add ( a : Int ){
fun add( b : String , c : Int){}
add( "bbb", a)
}
泛型函数
函数可以有泛型参数,通过在函数名前使用尖括号指定。与java基本相同
fun add( a : T) :T{
return a*2
}
尾递归函数
Kotlin 支持一种称为尾递归的函数式编程风格。 这允许一些通常用循环写的算法改用递归函数来写,而无堆栈溢出的风险。 当一个函数用tailrec修饰符标记并满足所需的形式时,编译器会优化该递归,留下一个快速而高效的基于循环的版本。
tailrec fun findFixPoint(x:Double= 1.0) :Double =
if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))使用尾递归的时候请注意:要符合tailrec修饰符的条件的话,函数必须将其自身调用作为它执行的最后一个操作。在递归调用后有更多代码时,不能使用尾递归,并且不能用在 try/catch/finally 块中。目前尾部递归只在 JVM 后端中支持。
lambda表达式
lambda表达式与高阶函数应用很密切,经常会遇到,在java中也支持lambda表达式,不过目前好像没多少人用,但真正用起来,的确也是提高代码的编写效率,而且不失可读性。
例如:
val sum = { x :Int , y :Int -> x + y }
lambda 表达式总是被大括号括着, 完整语法形式的参数声明放在括号内,并有可选的类型标注, 函数体跟在一个->符号之后。如果推断出的该 lambda 的返回类型不是Unit,那么该 lambda 主体中的最后一个(或可能是单个)表达式会视为返回值。
it 关键字应用:一个 lambda 表达式只有一个参数,如果 Kotlin 可以自己计算出签名,它允许我们不声明唯一的参数,并且将隐含地为我们声明其名称为it:
val boo { it >0}
默认: boo 是个函数,参数是 Int 类型
限定返回值:我们可以使用限定的返回语法从 lambda 显式返回一个值。否则,将隐式返回最后一个表达式的值。而且请注意,如果一个函数接受另一个函数作为最后一个参数,lambda 表达式参数可以在圆括号参数列表之外传递。 参见callSuffix的语法。
限定语法使用 @ 符号
ints.filter {
val shouldFilter= it >0
return@filter shouldFilter
}
总结:
除了这些当然还有内联函数、高阶函数等内容相对复杂,将放到下面的章节中学习。