Kotlin-改良的java(二)

Kotlin-改良的java(二)

20天打卡计划 day02

Kotlin-核心语法:

匿名函数:

对于上一篇最后的引用·函数表达方式还是不方便,因为我们每添加一个筛选需求就要在test类中增加一个筛选的方法,这对于追求语法简洁的Kotlin来说显然是不合理的,在Java中有匿名类来优化对象的创建,相应的,Kotlin引入了匿名函数(没有函数名的函数)来对程序作进一步优化:

App.findUser(users,                     //对应形参:users : List<User>
             fun(user : User) : Boolean //对应形参:testone : (User) -> Boolean
    {//匿名函数体
        return user.name == "汪涵" && user.gender == "男" && user.id == 1
    }
)//调用函数结束

Lambda表达式:

可以理解为简化后的匿名函数:

App.findUser(users,
			{user -> user.name == "汪涵" && user.gender == "男" && user.id == 1}//省略fun(user : User),编译器会自动推导类型(见前一篇文章的增强类型推导)
     //省略return 返回一个表达式
	 //->是模仿函数类型的写法,用->来连接参数和返回值,要区别和函数类型,不然后面会很绕
)

具体语法:

val sum:(Int, Int) -> Int = {x : Int, y :Int -> x +y}

由于增强的类型推导(记住冒号以后的是类型,除了一些类之类的特殊类型,其他类型可以省略),可以简化为:

val sum = {x, y -> x + y}

另外需要注意的是,如果Lambda表达式的返回值不是Unit,那么默认最后一行表达式的值的类型就是返回值的类型:

val foo = { x: Int, y: Int
	val sum = x +y
	sum
}

前面我们都是用Lambda表达式来实现匿名函数的效果,那如果我们用fun关键字来声明Lambda会怎么样呢?这里借用《Kotlin核心编程》中的例子:

fun foo(int : Int) = {
	print(int)
}
>>> listOf(1,2,3).forEach { foo(it).invoke() }

解释一下,在这里 it 是一个关键字,叫做单个参数的隐式名称,实际的效果是:

item -> foo(item)

invoke()方法 kotlin在JVM层设计了Function类型(Function0到Function22和FunctionN),后面的数字代表了Lambda参数的数量,如以上的foo函数构建的其实是一个无参的Lambda,所以对应的接口是Function0,如果有一个参数对应的就是Function1,每个Function类型都有一个invoke方法,我们调用foo函数,返回的其实是一个Function0类型,通过Function0类型的invoke方法来调用的实际的函数过程,kotlin的简洁表达理念提供了更简单的表达:

>>> listOf(1,2,3).forEach { foo(it)() }
123

最后我们来总结一下函数Lambda闭包

  • fun在没有等号、只有花括号的情况下,是我们最常见的代码块函数体,如果返回非Unit值,必须带return。
fun foo(x : Int) { print(x) }
fun foo(x : Int, y: Int): Int{ return x+y}
  • fun带有等号,是单表达式函数体。该情况下可以省略return。
fun foo(x: Int, y: Int) = x + y

val和fun等号加花括号的语法,构建的就是一个lambda的表达式,如果左侧是fun,那么就是Lambda表达式函数体,也必须通过invoke来调用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)  //x=1,y=2
  • 闭包:由花括号{}包裹的代码块如果访问了外部环境变量则被称为一个闭包,一个闭包可以当作参数传递或者直接使用,可以简单地看成访问+修改(与Java区别)外部环境变量的函数,Lambda就是最常见的闭包形式。

函数作为返回结果:

之前我们做过了函数作为参数传递的实例,了解到了函数怎么传(::引用方法),传什么(函数类型->)接下来我们介绍函数作为返回结果的实例:

一个表达式函数体的例子:

fun foo(x : Int) = {y: Int -> x + y}

可以等价于:

/*这里可能就有点晕了,再来强调一下,:是后面是变量的类型 ()-> 是函数类型的标志,没有括号是Lambda表达式的特殊写法*/
fun foo(x: Int): (Int) -> Int{
	return { y: Int -> x + y}
}

这里可以看到,我们的函数体返回的是(Int) -> Int类型的函数;

为了理解这种思想,我们来接好一种叫做”柯里化(Currying)的语法“

柯里化:指的是把接收多个参数的函数换成一系列只接收单一参数的函数的过程,在返回最终的结果值之前,前面的函数依次接收单个参数,然后返回给下一个新的函数。

用加法举例:

fun sum(x: Int, y: Int, z: Int) = x + y + z
sum(1, 2, 3)

现在按照柯里化的思路重新设计,最终就可以实现链式调用:

fun sum(x: Int) = {y: Int ->
	{z: Int -> x + y + z}
}
sum(1)(2)(3)

简单来说:柯里化就是只传递给函数一部分参数来调用它,让它返回一个新函数去处理剩下的参数

在这个加法程序中第一次调用sum(1)是得到了一个特定功能的函数,在这里是得到一个和1求和的函数,之后调用是传入了和1相加的数。

函数柯里化的这种作用,可以理解为参数复用,延迟执行,减少了代码冗余,增加了代码可读性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值