Android:Kotlin详细入门学习指南-高阶函数-基础语法(七)

本人也是在初学Kotlin,如有错误,请帮忙指出,持续更新

Android:Kotlin详细入门学习指南-高阶函数-基础语法(七)

建议先看看前面的文章
Android:Kotlin详细入门学习指南-基础语法(一)

Android:Kotlin详细入门学习指南-基本类型-基础语法(二)

Android:Kotlin详细入门学习指南-包-控制流-返回与跳转-基础语法(三)

Android:Kotlin详细入门学习指南-类和对象-基础语法(四)

Android:Kotlin详细入门学习指南-类和对象(下)-基础语法(五)

Android:Kotlin详细入门学习指南-函数-基础语法(六)

这篇文章分享的内容比较多,建议先关注收藏,再查看,以免迷路

高阶函数

高阶函数就是可以接受函数作为参数并返回一个函数的函数

字面函数和函数表达式

字面函数或函数表达式就是一个 "匿名函数",也就是没有声明的函数,但立即作为 表达式传递下去。

max(strings, {a, b -> a.length < b.length })

max 函数就是一个高阶函数,它接受函数作为第二个参数。第二个参数是一个表达 式所以本生就是一个函数,即字面函数。作为一个函数,相当于:

fun compare(a: String, b: String) : Boolean = a.length < b.lengt h
函数类型

一个函数要接受另一个函数作为参数,我们得给它指定一个类型。

fun max<T>(collection: Collection<out T>, less: (T, T) -> Boolean ): T? { 
    var max: T? = null 
    for (it in collection) 
        if (max == null || less(max!!, it)) 
            max = it 
            return max 
}

参数 less 是 (T, T) -> Boolean 类型,也就是接受俩个 T 类型参数返回一 个 Boolean :如果第一个参数小于第二个则返回真。 在函数体第四行, less 是用作函数

val compare: (x: T,y: T) -> Int = ...
函数文本语法
val sum = {x: Int,y: Int -> x + y}

函数文本总是在大括号里包裹着,在完全语法中参数声明是在括号内,类型注解是 可选的,函数体是在 -> 之后,像下面这样:

val sum: (Int, Int) -> Int = {x, y -> x+y }
函数文本有时只有一个参数。如果 kotlin 可以从它本生计算出签名,那么可以省略 这个唯一的参数,并会通过 it 隐式的声明它:

```kotlin
ints.filter {it > 0}//这是 (it: Int) -> Boolean 的字面意思

注意如果一个函数接受另一个函数做为最后一个参数,该函数文本参数可以在括号 内的参数列表外的传递。

函数表达式

上面没有讲到可以指定返回值的函数。在大多数情形中,这是不必要的,因为返回 值是可以自动推断的。然而,如果你需要自己指定,可以用函数表达式来做:

fun(x: Int, y: Int ): Int = x + y
闭包

一个字面函数或者表达式函数可以访问闭包,即访问自身范围外的声明的变量。不 像 java 那样在闭包中的变量可以被捕获修改:

var sum = 0 ins filter {it > 0} forEach { 
    sum += it 
}
print(sum)
内联函数

inline 标记即影响函数本身也影响传递进来的 lambda 函数:所有的这些都将被 关联到调用点。 内联可能会引起生成代码增长,但我们可以合理的解决它(不要内联太大的函数)

inline fun lock<T>(lock: Lock,body: ()-> T): T { //... }

为了你想要一些 lambda 表达式传递给内联函数时是内联的,你可以给你的一些函 数参数标记 @noinline 注解:

inline fun foo(inlined: () -> Uint, @noinline notInlined: () -> Unit) { //... }

内联的 lambda 只能在内联函数中调用,或者作为内联参数,但 @noinline 标记 的可以通过任何我们喜欢的方式操控:存储在字段,( passed around etc)

返回到非局部

在 kotlin 中,我们可以不加条件的使用 return 去退出一个命名函数或表达式函 数。这意味这退出一个 lambda 函数,我们不得不使用标签,而且空白的 return 在 lambda 函数中是禁止的,因为 lambda 函数不可以造一个闭合函数返回:

fun foo() { 
    ordinaryFunction { 
        return // 错误 不可以在这返回 
        } 
}

但如果 lambda 函数是内联传递的,则返回也是可以内联的,因此允许下面这样:

fun foo() { 
    inlineFunction { 
        return // 
        ] 
}

注意有些内联函数可以调用传递进来的 lambda 函数,但不是在函数体,而是在另 一个执行的上下文中,比如局部对象或者一个嵌套函数。在这样的情形中,非局部 的控制流也不允许在lambda 函数中。
内联 lambda 不允许用 break 或 continue ,但在以后的版本可能会支持。

实例化参数类型

有时候我们需要访问传递过来的类型作为参数:

fun <T> TreeNode.findParentOfType(clazz: Class<T>): T? { 
    var p = parent 
    while (p != null && !clazz.isInstance(p)) { 
        p = p?.parent 
    }
    @suppress("UNCHECKED_CAST") 
    return p as T 
}

现在,我们创立了一颗树,并用反射检查它是否是某个特定类型。一切看起来很 好,但调用点就很繁琐了:

myTree.findParentOfType(javaClass<MyTreeNodeType>() )

我们想要的仅仅是给这个函数传递一个类型,即像下面这样:

myTree.findParentOfType<MyTreeNodeType>()

为了达到这个目的,内联函数支持具体化的类型参数,因此我们可以写成这样:

inline fun <reified T> TreeNode.findParentOfType(): T? { 
    var p = parent 
    while (p != null && p !is T) { 
        p = p?.parent 
    }
    return p as T 
}

用 refied 修饰符检查类型参数,既然它可以在函数内部访问了,也就基本上接 近普通函数了。因为函数是内联的,所以不许要反射,像 !is `as`这样的操作 都可以使用。同时,我们也可以像上面那样调用它了

myTree.findParentOfType<MyTreeNodeType>()

尽管在很多情况下会使用反射,我们仍然可以使用实例化的类型参数 javaClass() 来访问它:

inline fun methodsOf<reified T>() = javaClass<T>().getMethods()
fun main(s: Array<String>) {
println(methodsOf<String>().joinToString('\n'))
}

普通的函数(没有标记为内联的)不能有实例化参数。

这篇文章主要分享Kotlin中的高阶函数.

本人也是在初学Kotlin,如有错误,请帮忙指出,持续更新

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容