Kotlin отмечает функции высокого порядка (7)

Kotlin отмечает функции высокого порядка (7)

Тип данных заметки Kotlin (1) Строка заметки Kotlin (2) Оператор заметки Kotlin (3) Функция заметки Kotlin (4) Объектно-ориентированная заметка Kotlin (5) Наследование заметки Kotlin, абстрактный класс, интерфейс (6)






1. Функции высшего порядка

Функция может использоваться как параметр другой функции или возвращать значение, тогда эта функция является «функцией более высокого порядка».

2. Тип функции

Каждая функция в Kotlin имеет тип, который называется «тип функции».Как тип данных,
нет разницы между типом функции и типом данных в сценариях использования.

//定义计算长方形面积函数
//函数类型(Double, Double) -> Double
fun rectangleArea(width: Double, height: Double): Double {
    
    return width * height
}
//定义计算三角形面积函数
//函数类型(Double, Double) -> Double
fun triangleArea(bottom: Double, height: Double) = 0.5 * bottom * height ②
fun sayHello() {
    
     //函数类型()->Unit ③
print("Hello, World")
}
fun main(args: Array<String>) {
    
    
val getArea: (Double, Double) -> Double = ::triangleArea ④
//调用函数
val area = getArea(50.0, 40.0)print(area) //1000.0
}

3. Функциональные литералы

Переменные функционального типа могут быть объявлены, так какие же данные могут получать переменные функционального типа? То есть, как выразить функциональный литерал
Функциональный литерал может быть выражен тремя способами:

  • ссылка на функцию. Ссылка на уже определенную именованную функцию. Его можно использовать как функциональный литерал.
  • анонимная функция. Функция без имени, то есть анонимная функция, также может использоваться как функциональный литерал.
  • Лямбда-выражения. Лямбда-выражения — это анонимные функции, которые можно использовать как функциональные литералы.
fun calculate(opr: Char): (Int, Int) -> Int {
    
    
//加法函数
fun add(a: Int, b: Int): Int {
    
    
return a + b
}
//减法函数
fun sub(a: Int, b: Int): Int {
    
    
return a - b
}
val result: (Int, Int) -> Int =
when (opr) {
    
    
'+' -> ::add ①
'-' -> ::sub ②
'*' -> {
    
    
//乘法匿名函数
fun(a: Int, b: Int): Int {
    
     
return (a * b)
}
}
else -> {
    
     a, b -> (a / b) } //除法Lambda表达式 ④
}
return result
}
fun main(args: Array<String>) {
    
    
val f1 = calculate('+')println(f1(10, 5)) //调用f1变量 ⑥
val f2 = calculate('-')
println(f2(10, 5))
val f3 = calculate('*')
println(f3(10, 5))
val f4 = calculate('/')
println(f4(10, 5))
}

4. Функция как возвращаемое значение

fun main(args: Array<String>) {
    
    

    var funName=getFunWithType(2)

    println(funName(1,3))
}
fun getFunWithType(type:Int):(Int,Int)->Int{
    
    
    var functionType:(Int,Int)->Int
    when(type){
    
    
        1-> functionType=fun (a:Int,b:Int):Int=a+b
        else -> functionType={
    
    a,b->a-b}
    }

    return functionType
}

5. Функции как параметры

fun main(args: Array<String>) {
    
    
    var funName=getFunWithType(2)
    println(operterFun(funName,4,5))
}
fun operterFun(funName:(Int,Int)->Int,a: Int,b: Int):Int{
    
    
    return funName(a,b)
}
fun getFunWithType(type:Int):(Int,Int)->Int{
    
    
    var functionType:(Int,Int)->Int
    when(type){
    
    
        1-> functionType=fun (a:Int,b:Int):Int=a+b
        else -> functionType={
    
    a,b->a-b}
    }

    return functionType
}

Два, лямбда-выражение

1. Стандартный синтаксис лямбда-выражения

{ список параметров -> тело лямбды }

Список параметров лямбда-выражения аналогичен списку параметров функции, но вокруг списка параметров лямбда-выражения
нет круглых скобок . Стрелочная нотация отделяет список параметров от тела Lambda, и в выражениях Lambda не нужно объявлять
возвращаемый тип. Лямбда-выражения могут иметь возвращаемое значение. Если нет оператора return, последнее выражение в теле Lambda
является возвращаемым значением лямбда-выражения. Если есть оператор return, возвращаемое значение — это выражение после оператора return
.

fun main(args: Array<String>) {
    
    

    var funLa={
    
    a:Int,b:Int-> a+b}

    println(funLa(2,4))

}

2. Упрощенное написание лямбда-выражений

{a:Int,b:Int-> a+b} можно упростить до
{a, b -> a + b}

Завершающая лямбда Если последним параметром функции является лямбда-выражение, то это лямбда-выражение
может быть помещено после круглых скобок функции.

fun main(args: Array<String>) {
    
    

    //正常调用
//    operterFun(2,3,{a,b->a+b})
    
    //尾随写法
    operterFun(2,3){
    
    a,b->
        a+b
    }
}

fun operterFun(a: Int,b: Int,funName:(Int,Int)->Int):Int{
    
    
    return funName(a,b)
}

Если есть только один параметр лямбда-выражения, и его тип данных можно вывести в соответствии с контекстом
, то объявление этого параметра можно опустить, а неявный параметр он используется в теле лямбда для замены параметра
лямбда -выражения.

fun main(args: Array<String>) {
    
    
    
    operterLa("zyb"){
    
     println(it)}

}


fun operterLa(name:String,funName: (String)->Unit){
    
    
    funName(name)
}

3. Лямбда-выражение и оператор return

Оператор return также можно использовать в теле лямбда-выражения, что приведет к выходу программы из тела лямбда-выражения.

fun main(args: Array<String>) {
    
    

    println(sum(1,2,3,10,3)) //9
    val add = label@ {
    
    
        val a = 1
        val b = 2
        return@label 10
        a + b
    }
//调用Lambda表达式add
    println(add()) //10
}


//累加求和函数
fun sum(vararg num: Int): Int {
    
    
    var total = 0
    num.forEach {
    
    
//        if (it == 10) return -1 //返回最近的函数 ②
        if (it == 10) return@forEach//返回Lambda表达式函数 ③
        total += it
    }
    return total
}

3. Замыкания и захват переменных

Closure (замыкание) — это специальная функция, которая может обращаться к переменным вне тела функции, эта переменная
существует вместе с функцией, даже если она покинула свою первоначальную область видимости. Эта специальная функция обычно является локальной функцией, анонимной
функцией или лямбда-выражением.

fun makeArray(): (Int) -> Int {
    
    
var ary = 0//局部函数捕获变量
fun add(element: Int): Int {
    
    
ary += element ④
return ary ⑤
}
return ::add ⑥
}
fun main(args: Array<String>) {
    
    
val f1 = makeArray()println("---f1---")
println(f1(10))//累加ary变量,输出结果是10
println(f1(20))//累加ary变量,输出结果是30
}

4. Встроенные функции

В функции высокого порядка, если параметр является типом функции, он может получить лямбда-выражение, а лямбда-выражение
компилируется как анонимный класс во время компиляции, и объект будет создаваться каждый раз при вызове функции. это неоднократно вызывается функцией.
Затем создайте много объектов, что приведет к дополнительным накладным расходам во время выполнения.
Чтобы решить эту проблему, такие функции можно объявлять как встроенные функции в Kotlin .
Подсказка, что встроенная функция не будет генерировать код вызова функции при компиляции, а заменит каждую функцию вызова фактическим кодом в теле функции
.

1. Определение встроенной функции

Используйте ключевое слово inline

inline fun calculatePrint(funN: (Int, Int) -> Int) {
    
    println("${funN(10, 5)}")
}
fun main(args: Array<String>) {
    
    
calculatePrint {
    
     a, b -> a + b }
calculatePrint {
    
     a, b -> a - b }}

2. Используйте функцию let

В Kotlin, когда параметр функции объявлен как ненулевой тип, он также может получать параметры типа, допускающего значение NULL, но если фактический параметр
действительно нулевой, это может вызвать серьезные проблемы. Следовательно, перед передачей параметра необходимо определить
, является ли параметр, допускающий значение NULL, ненулевым.

fun main(args: Array<String>) {
    
    


sayNameLength(null)
}


fun sayNameLength(name:String?){
    
    
//    if (name!=null){
    
    
//        println(name.length)
//    }
    name?.let {
    
    println(it.length) }
}

2. Используйте функции with и apply

Иногда вам нужно установить несколько свойств объекта или вызвать несколько функций, вы можете использовать функцию with или apply.
Подобно функции let, все объекты в Kotlin могут использовать эти две функции.

with возвращает последнее предложение выражения, а apply возвращает объект

fun main(args: Array<String>) {
    
    


//sayNameLength(null)


    var name=StringBuilder(0)

    var stringBuilder2=name.apply{
    
    
        append("hello")
        append("  ")
        append("world")

    }

    var stringBuilder3= with(name){
    
    
        this.append("\n")
        this.append("My name is ")
        this.append("zyb")
        "我是with"
    }

    println(name)
    println(stringBuilder2)
    println(stringBuilder3)

## hello  world
## My name is zyb
## hello  world
## My name is zyb
## 我是with
}

Supongo que te gusta

Origin blog.csdn.net/baidu_31956557/article/details/109290124
Recomendado
Clasificación