美文网首页
Kotlin---标准扩展函数

Kotlin---标准扩展函数

作者: None_Ling | 来源:发表于2018-12-03 16:19 被阅读8次

介绍

除了自定义扩展之外,Kotlin中也定义了很多的扩展函数,而这些扩展函数的接收类型是范型,也就是所有对象都可以使用。这些标准的扩展函数都放在了Standard.kt中。

从Kotlin的语言介绍中,可以知道,Kotlin在空指针以及null对象的控制、语句表达上有很多优势,很多优势也来源于Kotlin的扩展函数的支持。

接下来会介绍:

  • let
  • apply
  • run
  • takeIf
  • takeUnless
  • with

也会看看,这些函数是如何让空对象的代码更加优雅的表达。

let函数

首先来详细介绍一下let函数的定义,以及它是如何运行的。

/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
  1. 函数定义:
public inline fun <T, R> T.let(block: (T) -> R): R {
  • 使用inline关键字来标志这个函数是一个内联函数
  • <T,R>代表函数参数范型
  • T.let代表它是一个扩展函数,而接收参数是一个泛型
  • block:(T)->R代表函数的参数是一个代码块,而这个代码块接收参数T,并且返回R类型的对象
  • :R代表整个let函数返回类型是R类型

其中很重要的一个概念是:Kotlin中,所有的东西都是对象,所以代码块也是一个对象,可以使用变量引用。

  1. 函数体:
contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
  • contract代码块:主要为了告诉编译器,Lambda表达式会马上执行,并且只执行一次,因为在编译器编译的时候会对某些变量判空时,判断是否可以编译通过并且运行。
  • block(this):执行代码块中的代码,并且将调用扩展函数的对象作为参数传入,返回结果

let函数举例

例如下面的函数,如果student不为空的话,则会打印名字和年龄。

fun acceptStudent(student: Person?) {
        student?.let {
            println("Student Name:${it.mName}")
            println("Student Age:${it.mAge}")
        }
}

而如果这段代码用Java写的话,则是

if(student!=null) {
    println("student name:"+student.mName);
    println("student age:"+student.mAge)
}

apply函数

apply函数的定义如下:

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

可以看到它和let函数差不多,只有一些区别:

  • block代码块中没有参数,仅仅只执行代码块的代码,但是可以使用this关键字来指向本对象
  • 函数的返回值是this,而block代码块没有返回值

因为它返回的this,也可以配合let扩展函数来使用

fun acceptStudent(student: Person?) {
        student?.apply {
            println("Apply Name...${this.mName}")
        }.let {
            println("let Age...${it?.mAge}")
        }
    }

run函数

run函数的原型是:

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

可以看到,这个函数会执行代码块中的代码,并且将代码块执行的结果作为返回值返回。

例如:
gardenPlantTest函数中,在run代码块中打印完字符串plant,如果plant不为空返回字符串长度,否则返回0,而result中保存的也就是代码块中返回的字符串长度

class GardenPlant {
    lateinit var plant: String;

    fun gardenPlantTest() {
        var result = plant.run {
            println("Plant String...$this")
            plant?.length
        }
        println("Plant Length:$result")
    }
}

takeIf函数

takeIf的函数原型:
将扩展对象T作为参数,执行predicate代码块的代码,如果在代码块中返回true,则返回对象T,如果返回false,则返回null

/**
 * Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}

例如:
如果plant字符串大于10,就可以采用,如果不行的话,则返回null,下面的代码块中只是表示可以在代码块中使用if等条件判断语句,只要最后返回的结果是boolean值就可以。

class GardenPlant {
    lateinit var plant: String;

    fun gardenPlantTest() {
        val filetrPlant = plant.takeIf {
            if (plant.length > 10) {
                plant.length > 10
            } else {
                plant.length < 10
            }
        }
        println("Plant String Length >9 :$filetrPlant")
    }
}

在代码块中返回值,不能使用return关键字,因为return关键字会返回整个函数,而不是代码块

takeUnless函数

takeUnless函数原型如下:
takeIf不一样的是,返回的取值取反,来进行判断是否采用。

/**
 * Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (!predicate(this)) this else null
}

with函数

with函数不是一个扩展函数,它的原型如下:
这个函数主要会接收一个对象,然后调用该对象的扩展代码块,然后返回代码块中的值。

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

例如:
plant对象中替换完字符后,返回length,并且赋值给plantLength

class GardenPlant {
    lateinit var plant: String;

    fun gardenPlantTest() {
        var plantLength = with(plant) {
            replace('w', 'r')
            length
        }
    }
}

相关文章

  • Kotlin---标准扩展函数

    介绍 除了自定义扩展之外,Kotlin中也定义了很多的扩展函数,而这些扩展函数的接收类型是范型,也就是所有对象都可...

  • Kotlin---扩展

    介绍 除了与Java类比的这些功能之外,Kotlin还新增了一些新的概念 数据类(data) 扩展函数 密封类(s...

  • kotlin--扩展

    之间使用了kotlin的标准函数、匿名函数,觉得它十分灵活,简便。其实kotlin的标准函数就是用了扩展 一、扩展...

  • Swift 2 学习笔记 17.扩展和泛型

    课程来自慕课网liuyubobobo老师 扩展 扩展基础 扩展标准库 泛型函数 泛型类型

  • Kotlin 标准库扩展函数

    Kotlin 标准库提供了一些扩展 Java 库的函数。 apply apply 是 Any 的扩展函数, 因而所...

  • kotlin语法糖整理(持续更新)

    [TOC] 好吧..用MarkDown写的.. # Kotlin 标准库常用扩展函数集合 ## apply * a...

  • Kotlin标准库中的高阶函数

    Kotlin标准库中的高阶函数 Kotlin中的5个通用扩展函数这些函数都存在Standard.kt文件中,run...

  • Kotlin 笔记 扩展

    扩展(extension)是指向已有的类中添加函数 扩展函数 定义扩展函数时,在函数前面加上要扩展类的名字,以下代...

  • 2021-11-30(Kotlin学习笔记)Kotlin 基础(

    kotlin java 隔离 kotlin 扩展函数 java 中调用扩展函数 高级函数

  • OC-Block语法

    block 语法 block语法 -> 块语法标准C里面没有Block, C语言的后期扩展版本, 加入了匿名函数;...

网友评论

      本文标题:Kotlin---标准扩展函数

      本文链接:https://www.haomeiwen.com/subject/rkgjcqtx.html