函数是一个类型,就像编程语言中的基本类型一样,就像Java中的引用类型一样,函数是函数类型。基本类型、引用类型、函数类型,说白了物理空间就是内存的一段区域,逻辑空间叫什么基本类型、引用类型、函数类型。基本类型就是int, float这种存储数据的,引用类型就是类呗,一个类在内存中不也是一段区域嘛,函数类型就是一段操作流程呗,一段操作流程在内存中不也是一段区域嘛。总之一样啦。猫是动物,狗是动物,人家棕熊也是动物啦,都在地球上占据一定的空间,不能把人家当成空气。

     

既然他们都是一种类型,那就要同等对待,既可以作为变量,也可以作为常量;既可以作为函数形参,也可以作为函数返回值。猫和狗能结婚生子,人家棕熊也可以,不可以把人家阉割了。物物平等。

fun add(a: Int, b: Int) : Int {return a + b
}

上面这个棕熊,哦,不对,函数,上面这个函数的类型是啥?

不知道吧,我告诉你,是这个:

(Int, Int) -> Int

惊不惊喜?咦,看不懂?回去补补lambda表达式去,老衲不负责给你补基础知识。哇咔咔!

好啦,既然函数有类型了,那我们用函数声明变量吧,它和用基本类型,用类声明变量是一样一样嘀。

var myfun : (Int, Int) -> Int    //函数类型
var myBase : Float               //基本类型
var myClass : String             //引用类型

从此,江湖上出现了三剑客:基本类型、函数类型、引用类型。打遍天下无敌手。

定义完类型了,我得赋值啊,要不我定义类型干啥。

客官请看下面内容:

myfun = :: add   //使用函数引用要用::,不能加(),因为加()就变成调用函数了,而不是使用函数引用
myBase = 1.5f
myClass = String("你瞅啥,我就喜欢用String的构造函数咋地")  //实例化对象不需要用new了,直接用对象的构造函数
myClass = "当然,直接这样写也是可以的"

再来,函数类型作为形参:

fun sum(a: Int, b: Int, fn: (Int, Int) -> Int): Int {return fn(a, b)
}

我就喜欢把函数类型传进去,咋嘀!

再来,函数类型作为返回值:

fun getMathFunc(type: String): (Int, Int)-> Int {// 定义一个计算加法的局部函数fun add(a: Int, b: Int) : Int {return a + b;}// 定义一个计算减法的局部函数fun sub(a: Int, b: Int) : Int {return a - b;}// 定义一个计算乘法的局部函数fun mul(a: Int, b: Int) : Int {return a * b;}when(type) {"add" -> return ::add"sub" -> return ::subelse -> return ::mul}}fun main(args: Array<String>) {var mathFunc = getMathFunc("add")   //得到add函数println(mathFunc(5, 3))             //输出8mathFunc = getMathFunc("sub")       //得到sub函数println(mathFunc(5, 3))             //输出2mathFunc = getMathFunc("mul")       //得到mul函数println(mathFunc(5, 3))             //输出15
}

好啦,就说到这里吧,既然函数又能作为变量,又能作为形参,又能作为返回值,说不定还能作为常量(我猜测地,不过函数作为常量干啥,函数本身就是变化地,作为常量干啥,哈哈哈,完全没用,就像你把类实例化的对象作为常量干啥,也没用哇),那么函数这么厉害,和其他类型一样,就要给它和之前我们简单使用的函数做出区分,至少在名词上做出区分,这样才让人感觉高大上。记住,叫“高阶函数”!这个不重要,忘了也没事,别在意,就是个多余的名字嘛,之前的函数不被阉割掉,也不会出现这么个多余的名字。好吧,你可以这么理解,之前世界上的棕熊都是被阉割的,现在的棕熊才是正常的,和猫啊,狗啊一样,都能结婚生子。阿弥陀佛~~

我对自己是有要求嘀,是要求自己尽量写出更优雅的代码嘀,再来:

上面的局部函数太繁琐,替换成lambda表达式:

fun getMathFunc(type: String): (Int, Int)-> Int {when(type) {"add" -> return {a: Int, b: Int -> a + b}"sub" -> return {a: Int, b: Int -> a - b}else -> return {a: Int, b: Int -> a * b}}
}fun main(args: Array<String>) {var mathFunc = getMathFunc("add")   //得到add函数println(mathFunc(5, 3))             //输出8mathFunc = getMathFunc("sub")       //得到sub函数println(mathFunc(5, 3))             //输出2mathFunc = getMathFunc("mul")       //得到mul函数println(mathFunc(5, 3))             //输出15
}

另外,lambda表达式是可以根据上下文推断类型的,所以,我们还可以更简化,再来:

fun getMathFunc(type: String): (Int, Int)-> Int {when(type) {"add" -> return {a, b -> a + b}"sub" -> return {a, b -> a - b}else -> return {a, b -> a * b}}
}fun main(args: Array<String>) {var mathFunc = getMathFunc("add")   //得到add函数println(mathFunc(5, 3))             //输出8mathFunc = getMathFunc("sub")       //得到sub函数println(mathFunc(5, 3))             //输出2mathFunc = getMathFunc("mul")       //得到mul函数println(mathFunc(5, 3))             //输出15
}

终于可以OVER了~~~

且慢,谢谢颜文大神的指点,getMathFunc函数还可以使用“=”来赋值。

fun getMathFunc(type: String):(Int, Int) -> Int = when(type) {"add" -> {a, b -> a + b}"sub" -> {a, b -> a - b}else -> {a, b -> a * b}
}

可以使用“=”赋值的有表达式和匿名函数,when语句可以这样写的话,我理解when语句应该是表达式吧?是吧?是吧?

查了下资料,果然如此。Kotlin中的if语句和when语句都可以作为表达式。

if语句作为if表达式时,这样写:

var str = if (age > 20) "age 大于20" else if(age < 20) "age小于20" else "age等于20"

when语句作为when表达式时,这样写:

var str = when (score) {'A' -> {println("望百尺竿头更进一步")"优秀"}'B' -> "良好"'C' -> "中"'D' -> "及格"else -> "不及格"
}

让我们再总结一下吧,表达式也可以给变量、常量赋值。

再让我们看下前面的例子吧,都哪些内容可以给变量赋值呢?

var myfun = :: add   //使用函数引用要用::,不能加(),因为加()就变成调用函数了,而不是使用函数引用
var myBase = 1.5f
var myClass = String("你瞅啥,我就喜欢用String的构造函数咋地")  //实例化对象不需要用new了,直接用对象的构造函数
// var myClass = "当然,直接这样写也是可以的"
var myExpression = if (age > 20) "age 大于20" else if(age < 20) "age小于20" else "age等于20"  //表达式也可以直接赋值哦

相比于前面,又多个一种可以给变量赋值的,就是表达式。

再让我们从另一个角度考虑,既然变量声明可以用var表示,函数声明用fun表示,而所谓的声明,就是给起个名字而已,从栈中发出一个指针。变量var声明的指针可以指向常量、函数、对象、表达式,而函数fun声明的指针指向的只有函数么?不是的,函数声明的指针还可以指向表达式。细心的读者可以看到我前面的例子中,表达式也是可以给函数类型赋值的。

将if表达式赋给函数类型:

fun getMathFunc(age: Int):String = if (age > 20) "age大于20" else if(age < 20) "age小于20" else "age等于20"fun main(args: Array<String>) {println(getMathFunc(25))      //输出“age大于20”
}

将when表达式赋给函数类型:

fun getMathFunc(type: String):(Int, Int) -> Int = when(type) {"add" -> {a, b -> a + b}"sub" -> {a, b -> a - b}else -> {a, b -> a * b}
}

用表达式来给函数赋值也有一个名字,叫单表达式函数。

接着让我们再开一下脑洞,既然我前面说了基本类型、函数类型、类的引用类型都是一样一样的东东,那么表达式是否可以给类的引用类型赋值呢?

反正Java8中的lambda表达式是给函数式接口赋值的,不过那是因为Java8的lambda表达式不是纯函数,而是通过函数式接口实现的,所以对于Kotlin的表达式,在这方面也没有什么类比价值。

留给你去思考吧。欢迎留言讨论。

最后,让我们再想想,既然表达式能够赋值给变量,我们还赋值给函数干嘛?这不是多此一举嘛。

这个要从变量和函数的作用说起,函数是一段代码的封装,有传参用的形参和返回值,比如when表达式括号中的参数,可以是函数的形参传过来的。而如果赋值给变量的话,when表达式括号中的参数就必须在给该变量赋值之前指定。这完全是一种顺序化的代码执行逻辑,而不是函数调用逻辑。所以说,两者在功能上是不一样的。

请看下面代码:

//赋值给变量
var type = "add"
var mathFunc2:(Int, Int) -> Int = when(type) {"add" -> {a, b -> a + b}"sub" -> {a, b -> a - b}else -> {a, b -> a * b}
}//赋值给函数
fun getMathFunc(type: String):(Int, Int) -> Int = when(type) {"add" -> {a, b -> a + b}"sub" -> {a, b -> a - b}else -> {a, b -> a * b}
}fun main(args: Array<String>) {var mathFunc = getMathFunc("add")   //得到add函数println(mathFunc(5, 3))             //输出8println(mathFunc2(5, 3));     // 输出8
}

就到这里吧。

转载于:https://my.oschina.net/tingzi/blog/1825245

Kotlin-高阶函数相关推荐

  1. Kotlin高阶函数及Lambda表达式实现接口回调

    文章目录 什么是高阶函数? Lambda 表达式 使用Kotlin高阶函数实现接口回调 Java中接口使用 Kotlin中接口使用 什么是高阶函数? 高阶函数是将函数作为参数或者返回值的函数. 特点 ...

  2. kotlin 高阶函数 代替 接口回调

    1 Java的接口回调 在Java当中,使用接口回调的形式传递数据很常见,定义接口,声明接口,在A类中传入接口的实例对象,就可以接收传入的数据index.而在kotlin中,比较简单,传入一个函数即可 ...

  3. Kotlin——高阶函数详解与标准的高阶函数使用

    一.高阶函数介绍 在介绍高阶函数之前,或许您先应该了解Kotlin中,基础函数的使用与定义.您可以参见Kotlin--初级篇(七):函数(方法)基础使用这边文章的用法. 在Kotlin中,高阶函数即指 ...

  4. kotlin高阶函数的初级理解

    1.定义 如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,那么该函数就称为高阶函数. 系统中已经有很多,示例:库函数 在 Standard.kt 标准库中提供了一些便捷的内置高阶函数 ...

  5. Kotlin 高阶函数

    高阶函数的基本概念 传入或者返回函数的函数 函数引用 ::println 带有Receiver的引用 pdfPrinter::println fun main(args: Array<Strin ...

  6. Kotlin高阶函数概念

    一.高阶函数的基本概念 1.传入或者返回函数的函数(传入是函数,返回也是函数) 2.函数引用最常见的方式,":: println" 3.带有接收者Receiver的引用pdfPri ...

  7. Kotlin——高阶函数

    这里写目录标题 1. 高阶函数 1.1 高阶函数定义 1.2 函数类型定义 1.3 高阶函数的用途 2. 高阶函数高级用法 2.1 apply函数 2.2 写一个自己的apply函数 3. inlin ...

  8. Kotlin高阶函数

    1.高阶函数定义 函数的参数接收的是另一个函数,或者返回值是另一个函数类型,我们把这类函数称为高阶函数 2.函数类型 字符串的类型用String表示,整型用Int表示,那么函数的类型呢? // 参数b ...

  9. android kotlin 高阶函数,Kotlin-高阶函数

    函数是一个类型,就像编程语言中的基本类型一样,就像Java中的引用类型一样,函数是函数类型.基本类型.引用类型.函数类型,说白了物理空间就是内存的一段区域,逻辑空间叫什么基本类型.引用类型.函数类型. ...

  10. android kotlin 高阶函数,(三)Kotlin 高阶函数

    温馨提示 写博客是为了记录在开发过程中所涉及到的技术以及遇到的问题的解决,如果该博客对您有所帮助,希望可以点个关注/喜欢:如果您对文章中的内容有什么不同的见解,欢迎留言进行讨论.谢谢! 一.基本概念 ...

最新文章

  1. norm--求矩阵和向量的范数
  2. [六字真言]1.唵.遁入佛门之异常.md
  3. java 解析p12_java读取*.p12证书的信息 | 学步园
  4. Linux系统安装pgp教程,在Linux系统下安装pgpcommandline
  5. MySQL数据库备份的三种方式
  6. 8bit/10bit线路编码简介
  7. 【Android 教程系列第 23 篇】 java 方法之间怎么添加分割线
  8. Excel应用-各地GDP的综合对比图表-Part2(平均线图、复合饼图、瀑布图、帕累托图)
  9. 艾默生质量流量计调试
  10. 启科量子可视化量子编程——QuComposer
  11. iOS 设置个人头像
  12. RGB和YUV颜色对比,使用ffmpeg颜色处理,视频混合,透明度处理
  13. java派单策略_滴滴KDD2018:强化学习派单
  14. 【项目】实现一个mini的tcmalloc(高并发内存池)
  15. Oracle Form二次开发实战总结
  16. 目标检测YOLOv2最详细解释!
  17. arcgis使用python脚本批量裁剪影像
  18. 【敬伟ps教程】蒙版和通道的基础知识
  19. 朋友圈炫富骗局曝光:那些“高端”的骗子是怎么骗人的?
  20. SAP 过账显示不在允许过账期间 消息号M7053

热门文章

  1. 业务中台如何提升研发效率
  2. 编码——隐匿在计算机软硬件背后的语言
  3. .Net软件设计新思维
  4. 随机森林(Random Forest)通俗教程
  5. 机器学习中的数学(二):参数估计与似然函数(MLE)
  6. HTML - 脚本JavaScript
  7. windowsf进程管理器中进程解释
  8. Matlab中数组的常见用法
  9. 通用html解析器,razor-从外部存储的.cshtml解析Rarzor HTML帮助器
  10. 7-4 输出三角形字符阵列 (15 分)