05kotlin之lamada

kotlin之lamada以及接收者类型

1.函数l默认参数

fun read(b: String, off: Int = 0, len: Int = b.length) {
    println("$b$off$len")
}
fun main(args: Array<String>) {
    read("ab")

    foo2(b = "nihao") // 具名参数
}

2.vararg函数表达式

fun double(x: Int): Int = x * 2
fun double2(x: Int) = x * 2 //是一样的, 有返回值

fun xPrint(x: String) = print(x) // 无返回值,根据最后类型来确定是否返回

varargs,打散,等价于java中…

fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}
使用时加*
    var arr = arrayOf(1, 2, 3)
    var result2 = asList(*arr) // 针对数组,需要打散,与java不同

3.infix 中缀

1.它们必须是成员函数或扩展函数;

2.它们必须只有一个参数;

3.其参数不得接受可变数量的参数且不能有默认值

类似于扩展函数,但是只有一个参数

infix fun Int.shl(x: Int): Int {
    return 0
}

fun Int.cx(x: Int): Int {
    return 2
}

fun main(args: Array<String>) {
    1.shl(2)
// 用中缀表示法调用该函数
    1 shl 2

    println(1.cx(2))
}

4.尾部递归函数tailrec

在传统的递归中,高级语言内存问题一致是一个很大的问题,

当一个函数用 tailrec 修饰符标记并满足所需的形式时,编译器会优化该递归,留下一个快速而高效的基于循环的版本:
val eps = 1E-10 // "good enough", could be 10^-15
tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))


/**
 * 相当于这种传统的方法,但更加适合于递归
 */
const val eps2 = 1E-10 // "good enough", could be 10^-15
private fun findFixPoint(): Double {
    var x = 1.0
    while (true) {
        val y = Math.cos(x)
        if (Math.abs(x - y) < eps2) return x
        x = Math.cos(x)
    }
}

5.高阶函数

1.lamada函数
//lamada表达式
val sum = { x: Int, y: Int ->
    println("求和")
    x + y
}
2.引用高阶函数

Int::times

// 函数引用也可以用于高阶函数调用:
val product = items.fold(1, Int::times)
/**
 * 声明函数
 */
val onClick: () -> Unit = { println(1) }

6.lamada表示

1.Function1<Int,String> String为返回值
val func: Function1<Int, String> = { "预约 ${it * 3}"}
println(func(1));
2.lamada表达式
    val func2 = fun(a: Int): String {
        return "预约 ${a * 3}"
    }
    val func3: (Int) -> String = { i: Int -> "预约 ${i * 3}" }
    val func4: (Int) -> String = { "预约 ${it * 3}" }//单个参数时,可以省略

4.函数引用
fun get(i: Int): String {
    return "${i * 3}"
}
5.匿名函数
    //lamada表达式
    val sum = { x: Int, y: Int ->
        println("求和")
        x + y
    }
    //匿名函数
    val sum2 = fun(x: Int, y: Int): Int {
        return x + y
    }
4.函数作为参数
fun testLambda(s: String, block: () -> String) {
    println(s)
    block()
}
//调用
    testLambda(value2, fun(): String {
        return value2
    })
    //原理
    val test: () -> String = { value2 }
    testLambda(value2, test)

7.lamda匿名接口

只有一个函数的时候

/**
 * class实现匿名接口
 * 匿名接口只有一个函数时,可用
 */
class IntTransformer : (Int) -> Int {
    override fun invoke(p1: Int): Int {
        return p1
    }
}

等价于下面

//等价于下面地方式
interface IntTransformerInterface {
    fun invoke(a: Int)
}

class MyInClass : IntTransformerInterface {
    override fun invoke(a: Int) {
        TODO("Not yet implemented")
    }
}

fun main(args: Array<String>) {
    val intFunction: (Int) -> Int = IntTransformer()
    //函数类型的值可以通过其 invoke(……) 操作符调用:f.invoke(x) 或者直接 f(x)。
    println(intFunction.invoke(1))
    println(intFunction(2))
}

8接收者函数调用

1.函数方式
    //函数方式
    val stringPlus: (String, String) -> String = 		     String::plus //第一个参数作为this,this::plus
    println(stringPlus.invoke("<-", "->"))
    println(stringPlus("Hello, ", "world!"))
2.接收者类型

非常类似于扩展函数,其实本质差不多

//返回函数类型
val intPlus: Int.(Int) -> Int = Int::plus //返回函数类型,

 val intPlus2 = fun Int.(other: Int): Int = this + other //扩展函数
 intPlus0.invoke(2, 3)
 println(intPlus.invoke(1, 1))
 println(intPlus(1, 2))
 println(2.intPlus(3)) // 类扩展调用
3.接受者作为参数
    val intPlus3: Int.(Int) -> Int = Int::plus
    add3(2, 3, intPlus3)


    //不会有返回值
    add4(2, 3) { a: Int, b: Int ->
        println("$a$b")
        a + b
    }

    //有返回值
    add5(2, 3) { a: Int, b: Int ->
        println("$a$b")
        a + b
    }

fun add3(a: Int, d: Int, b: Int.(Int) -> Int) {
    var c = a.b(d)
}

/**
 * 返回函数类型
 */
fun add4(a: Int, b: Int, c: (Int, Int) -> Int) = c

/**
 * 返回值类型
 */
fun add5(a: Int, b: Int, c: (Int, Int) -> Int) = c(a, b)

9.map细致说明

package day4lamada

fun main(args: Array<String>) {
    var map = mapOf(
            "name" to "John Doe",
            "age" to 25
    )
    var forMethod4: (Map.Entry<String, Any>) -> Unit = { (k1, v2) ->
        println(v2)
    }
    map.forEach(forMethod4) //正确调用
    map.forEach { forMethod4 } //错误调用,因为有两个参数,多个参数必须显性显示出来
}

10.闭包原理

函数也可以作为对象,持有函数内部的使用属性

package day4lamada

/**
 * 闭包原理,简单记住:函数也是对象,会将写入的值当作属性一直保存,直到该函数不在被引用
 *
 * 函数是一等公民,也是对象可以调用的
 * 弊端:带来内存的开销:每一个函数都是一个对象,并且会捕获一个闭包。
 */
fun main(args: Array<String>) {
    var method: () -> Unit = sum() //我们需要将函数当作对象,a是它的属性(内部变量),这样理解就非常简单了,万物皆对象,函数也不例外,其他语言就是如此
    method()
    method()
    method()
    var method2: () -> Unit = sum()
    method2()

}

fun sum(): () -> Unit {
    var a = 0
    return fun() {
        a++
        println(a)
    }
}

11.reified使用

这个很重要,在后面Android中,讲解

= sum() //我们需要将函数当作对象,a是它的属性(内部变量),这样理解就非常简单了,万物皆对象,函数也不例外,其他语言就是如此
method()
method()
method()
var method2: () -> Unit = sum()
method2()

}

fun sum(): () -> Unit {
var a = 0
return fun() {
a++
println(a)
}
}


### 11.reified使用

这个很重要,在后面Android中,讲解





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值