Kotlin笔记 函数

Infix

Infix 函数是:

  • 如果函数是成员函数或者extension 函数
  • 如果只有一个参数
  • 标注了infix
// Define extension to Int
infix fun Int.shl(x: Int): Int {
...
}

// call extension function using infix notation

1 shl 2

// is the same as

1.shl(2)

函数默认值

fun read(b: Array, off: Int = 0, len: Int = b.size()) {
  ...
}

如果子类要覆盖父类的方法,函数声明的时候需要沿用父类的默认值,不能重写默认值

//open class A {
    open fun foo(i: Int = 10) { ... }
}

class B : A() {
    override fun foo(i: Int) { ... }  // no default value allowed
}

命名参数

fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             divideByCamelHumps: Boolean = false,
             wordSeparator: Char = ' ') {
...
}

reformat(str,
    normalizeCase = true,
    upperCaseFirstLetter = true,
    divideByCamelHumps = false,
    wordSeparator = '_'
)

Varargs

函数参数可以被标记为vararg,参数会被当做数组:

fun  asList(vararg ts: T): List {
    val result = ArrayList()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}

只有一个参数能被标记为vararg,如果vararg参数不是最后一个参数,其他参数只能通过命名参数来传递。

局部函数

局部函数是定义在函数内部的函数,它可以访问外部函数的变量

fun dfs(graph: Graph) {
    fun dfs(current: Vertex, visited: Set) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
            dfs(v, visited)
    }

    dfs(graph.vertices[0], HashSet())
}

泛型函数

泛型函数将泛型参数放在函数名之前

fun  singletonList(item: T): List {
    // ...
}

Extension函数

向已有的对象添加函数,函数里的this代表对象

fun MutableList.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp
}

高阶函数

高阶函数将其他函数作为参数传入

fun  lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    }
    finally {
        lock.unlock()
    }
}

如果最后一个参数是函数,而且传入的是lambda函数,则可以把lambda函数写在括号外,如果传入的是匿名函数,则不能写在括号外:

lock (lock) {
    sharedResource.operation()
}

如果lambda函数只有一个参数,可以用it来指代

函数参数需要声明函数的type:

fun  max(collection: Collection, less: (T, T) -> Boolean): T? {
    var max: T? = null
    for (it in collection)
        if (max == null || less(max, it))
            max = it
    return max
}

函数类型里也可以指定参数名称

val compare: (x: T, y: T) -> Int = ...

匿名函数

fun(x: Int, y: Int): Int = x + y

如果是单行的表达式,返回值的类型可以推导出,可以省略,如果是block,那么返回值的类型需要指定,否则就是Unit

lambda表达式的return是退出外围的函数,而匿名函数的return是退出自己

闭包

lambda表达式和匿名函数都可以访问外围作用域的变量,与Java不同的是,Kotlin允许修改闭包里的变量(Java闭包的变量需要声明为final)

带Receiver的字面函数(好难理解)

你可以定义一个函数,指定这个函数的Receiver,Receiver为一个类

sum : Int.(other: Int) -> Int

然后在这个类的实例上调用这个函数

1.sum(2)

inline 函数

inline 之前

lock(l) { foo() }

inline 之后

inline fun lock(lock: Lock, body: () -> T): T {
    // ...
}
==>
l.lock()
try {
    foo()
}
finally {
    l.unlock()
}

inline 会展开调用函数和lambda参数,如果不想lambda参数被展开,可以在lambda参数前加上noinline

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
    // ...
}

lambda表达式中不允许使用不带标签的return语句(因为lambda中return是退出外围的函数,这叫non-local return),但如果lambda是传入到一个inline函数中,则可以return

你可能感兴趣的:(Kotlin笔记 函数)