在Kotlin中,高阶函数是指将一个函数作为另一个函数的参数或者返回值。如果用f(x)、g(x)用来表示两个函数,那么高阶函数可以表示为f(g(x))。Kotlin为开发者提供了丰富的高阶函数,比如Standard.kt中的let、with、apply等,_Collectioins.kt中的forEach等。为了能够自如的使用这些高阶函数,我们有必要去了解这些高阶函数的使用方法
创新互联公司是一家网站设计公司,集创意、互联网应用、软件技术为一体的创意网站建设服务商,主营产品:成都响应式网站建设、品牌网站制作、成都全网营销推广。我们专注企业品牌在网站中的整体树立,网络互动的体验,以及在手机等移动端的优质呈现。成都网站设计、成都网站制作、移动互联产品、网络运营、VI设计、云产品.运维为核心业务。为用户提供一站式解决方案,我们深知市场的竞争激烈,认真对待每位客户,为客户提供赏析悦目的作品,网站的价值服务。
今天我们来讲解高阶函数
- public fun test2(test:Int,block:()->Unit){
- var v= block()
- DTLog.i("TestTest","Test1")
- }
- public fun T.test22(block:()->T):T{
- return block()
- }
- public fun T.test26(block:T.()->Unit){
- block()
- }
- public fun T.test23(block:(T)->Unit):T{
- return this
- }
- public fun
- var t=block(this)
- return t
- }
- public fun
- return block(this)
- }
以上就是一个高阶函数,它接收了一个函数类型的参数,而调用高阶函数的方法与调用普通函数差异不大,只需要在参数名后面加上括号,并在括号中传入必要的参数即可;
高阶函数类型具有与函数签名相对应的特殊表示法,即它们的参数和返回值:
①内联函数是什么
inline(小心,不是online),翻译成“内联”或“内嵌”。意指:当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。这样做的好处是省去了调用的过程,加快程序运行速度。(函数的调用过程,由于有前面所说的参数入栈等操作,所以总要多占用一些时间)。这样做的不好处:由于每当代码调用到内联函数,就需要在调用处直接插入一段该函数的代码,所以程序的体积将增大。拿生活现象比喻,就像电视坏了,通过电话找修理工来,你会嫌慢,于是干脆在家里养了一个修理工。这样当然是快了,不过,修理工住在你家可就要占地儿了。内联函数并不是必须的,它只是为了提高速度而进行的一种修饰。要修饰一个函数为内联型
使用如下格式:
inline 函数的声明或定义
简单一句话,在函数声明或定义前加一个 inline 修饰符。
- inline int max(int a, int b)
- {
- return (a>b)? a : b;
- }
内联函数的本质是,节省时间但是消耗空间。
②内联函数规则
inline函数的规则
(1)、一个函数可以自已调用自已,称为递归调用(后面讲到),含有递归调用的函数不能设置为inline;
(2)、使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline;
(3)、由于inline增加体积的特性,所以建议inline函数内的代码应很短小。最好不超过5行。
(4)、inline仅做为一种“请求”,特定的情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。出现这种情况,编译器会给出警告消息。
(5)、在你调用一个内联函数之前,这个函数一定要在之前有声明或已定义为inline,如果在前面声明为普通函数,而在调用代码后面才定义为一个inline函数,程序可以通过编译,但该函数没有实现inline。比如下面代码片段:
- //函数一开始没有被声明为inline:
- void foo();
- //然后就有代码调用它:
- foo();
- //在调用后才有定义函数为inline:
- inline void foo()
- {
- ......
- }
代码是的foo()函数最终没有实现inline;
(6)、为了调试方便,在程序处于调试阶段时,所有内联函数都不被实现
③内联函数时应注意以下几个问题
(1) 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享。
(2) 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数。
(3) 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。
(4) 内联函数要在函数被调用之前声明。关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。
直使用的 Lambda 表达式在底层被转换成了匿名类的实现方式。这就表明,我们每调用一次 Lambda 表达式,都会创建一个新的匿名类实例,当然也会造成额外的内存和性能开销。为了解决这个问题,Kotlin 提供了内联函数的功能,它可以将使用 Lambda 表达式带来的运行时开销完全消除,只需要在定义高阶函数时加上 inline 关键字的声明即可
- inline fun test111(num1: Int, num2: Int, block: (Int, Int) -> Int): Int {
- val result = block(num1, num2)
- return result
- }
闭包函数 一个函数的返回值是函数,函数的内部包含另一个函数,可以是有参无参的匿名函数
- fun main(args: Array) {
- val mm = aaa()
- println(mm())
- println(mm())
- println(mm())
- println(mm())
- println(mm())
- val kk = bbb()
- println(kk("shadow")) //shadow --- 1
- println(kk("shadow")) //shadow --- 2
- println(kk("shadow")) //shadow --- 3
- println(kk("shadow")) //shadow --- 4
- println(kk("shadow")) //shadow --- 5
- }
- //闭包函数 就是函数作为返回参数
- fun aaa(): () -> (Int) {
- var current = 10
- return fun(): Int {
- return current++
- }
- }
- fun bbb(): (String) -> (String) {
- var current = 0;
- return fun(str: String): String {
- current++;
- return "$str --- $current";
- }
- }
在 Kotlin 源码的Standard.kt标准库中提供了一些便捷的内置高阶函数( let、also、with、run、apply ),可以帮助我们写出更简洁优雅的 Kotlin 代码,提高开发效率,学习源码可以更快的帮助我们理解和应用
- @kotlin.internal.InlineOnly
- public inline fun T.apply(block: T.() -> Unit): T {
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- block()
- return this
- }
- val str = "hello"
- str.apply { length } //可以省略 str.
- str.apply { this.length } //可以这样
- @kotlin.internal.InlineOnly
- public inline fun
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- return block(this)
- }
- @kotlin.internal.InlineOnly
- @SinceKotlin("1.1")
- public inline fun T.also(block: (T) -> Unit): T {
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- block(this)
- return this
- }
执行一个 T 类型中的方法,变量等,然后返回自身 T;
传递it作为block函数参数(调用时不可以省略),且also函数的返回值是调用者本身;
这个方法与上面的 apply 方法类似,只是在大括号中执行 T 自身方法的时候,必须要加上 T. 否则无法调用 T 中的 API,什么意思呢?看下面代码:
- val str = "hello"
- str.also { str.length } //str.必须加上,否则编译报错
- str.also { it.length } //或者用 it.
- @kotlin.internal.InlineOnly
- public inline fun
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- return receiver.block()
- }
- val str = "hello"
- val ch = with(str) {
- get(0)
- }
- println(ch) //打印 h
- @kotlin.internal.InlineOnly
- public inline fun run(block: () -> R): R {
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- return block()
- }
- @kotlin.internal.InlineOnly
- public inline fun
- contract {
- callsInPlace(block, InvocationKind.EXACTLY_ONCE)
- }
- return block()
- }
- run {
- println(888)
- }
- val res = run { 2 + 3 }
- fun runDemo() {
- println("测试run方法")
- }
- //我们可以这么干
- run(::runDemo)
- public inline fun T.takeIf(predicate: (T) -> Boolean): T? {
- contract {
- callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
- }
- return if (predicate(this)) this else null
- }
- val str = "helloWorld"
- str.takeIf { str.contains("hello") }?.run(::println)
- public inline fun T.takeUnless(predicate: (T) -> Boolean): T? {
- contract {
- callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
- }
- return if (!predicate(this)) this else null
- }
这个方法跟 takeIf() 方法类似,只是内部判断为false的时候返回自身T ,而 true 的时候返回 null,因此不过多说明,使用参考 takeIf() 方法。
- public inline fun repeat(times: Int, action: (Int) -> Unit) {
- contract { callsInPlace(action) }
- for (index in 0 until times) {
- action(index)
- }
- }
分析:repeat 方法包含两个参数:
- public inline fun repeat(times: Int, action: (Int) -> Unit) {
- contract { callsInPlace(action) }
- for (index in 0 until times) {
- action(index)
- }
- }
不管是 Kotlin 中内置的高阶函数,还是我们自定义的,其传入的代码块样式,无非以下几种:
这种在使用 (::fun) 形式简化时,要求传入的方法必须是无参数的,返回值类型如果是T则可为任意类型,否则返回的类型必须要跟这个代码块返回类型一致
这种在使用 (::fun) 形式简化时,要求传入的方法必须包含一个T类型的参数,返回值类型如果是R则可为任意类型,否则返回的类型必须要跟这个代码块返回类型一致。例如 with 和 apply 这两个方法
这种在使用 (::fun) 形式简化时,要求传入的方法必须包含一个T类型的参数,返回值类型如果是R则可为任意类型,否则返回的类型必须要跟这个代码块返回类型一致。例如 let 和 takeIf 这两个方法
当前标题:一篇带给你Kotin高阶函数详解
浏览地址:http://www.36103.cn/qtweb/news29/4229.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联