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中,讲解