我们需要掌握的Kotlin之各种函数

    xiaoxiao2025-06-23  14

    Kotlin的函数可以定义在文件顶部,也就是说不需要创建一个类来持有一个函数。另外,Kotlin函数还包括:本地函数、成员函数、扩展函数、内联函数、高阶函数、泛型函数、递归函数。

    一、本地函数

    本地函数是函数内部包含另一个函数,也就是函数嵌套,示例代码如下:

    fun dfs(graph: Graph) { fun dfs(current: Vertex, visited: Set<Vertex>) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) } dfs(graph.vertices[0], HashSet()) }

    本地函数可以访问外部函数的本地变量,因此上述例子可以这样写:

    fun dfs(graph: Graph) { val visited = HashSet<Vertex>() fun dfs(current: Vertex) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v) } dfs(graph.vertices[0]) }

    二、成员函数

    成员函数是定义在类内部,与Java一样,示例代码如下:

    class Sample() {     fun hello() { print("Hello World") } }

    成员函数可以使用点引用来调用:

    Sample().hello()

    三、泛型函数

    泛型函数是指函数中,参数或返回值类型定义成泛型,使用T表示:

    fun <T> singletonList(item: T): List<T> { print("This is generic function") }

    四、内联函数

    内存分配(包含函数对象和类)和虚函数调用,会带来运行时开销。但是,这些开销可以通过内联的lambda表达式来消除。对于编译器来说,我们需要使用inline修饰符来标识:

    inline fun <T> lock(lock: Lock, body: () -> T): T { print("This is an inline function") }

    内联修饰符会影响函数本身和lambda传递,这些都要内联到调用端。内联可能会引起代码增长。但是,如果我们使用恰当(避免在庞大函数中使用),它可以提升性能。

    1、noinline

    如果,我们只想某个lambda表达式内联,而不是整个函数内联。我们可以使用inlined和ontInlined修饰符来标识:

    inline fun hello(inlined: () -> Unit, noinline notInlined: () -> Unit) { print("This is inlined lambda") }

    2、crossinline

    有些函数传递lambda参数不是通过函数体本身,而是从另一个执行体,比如本地对象或者嵌套函数。这种情况下,non-local控制流也不允许出现在lambda表达式中。这时,需要使用crossline修饰符来标识:

    inline fun f(crossinline body: () -> Unit) { val f = object: Runnable { override fun run() = body() } }

    3、inline properties

    内联修饰符可以用于属性的访问,我们可以这样注解单个属性:

    val foo: Foo inline get() = Foo() var bar: Bar get() = ... inline set(v) { ... }

    五、扩展函数

    Kotlin提供类的扩展功能,不必用继承类的方法或者使用装饰者的设计模式。可以通过extensions来特殊声明,Kotlin支持扩展函数和扩展属性。声明一个扩展函数,我们需要在名称前面加一个接收类型。如下代码是往MutableList<Int>添加swap功能:

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

    扩展函数中的this关键字对应接收者类型。现在,我们可以调用MutableList<Int>中的swap方法:

    val l = mutableListOf(1, 2, 3) l.swap(0, 2)

    六、高阶函数

    高阶函数是把函数作为参数或者返回值的函数。示例代码如下:

    fun <T, R> Collection<T>.fold( initial: R, combine: (acc: R, nextElement: T) -> R ): R { var accumulator: R = initial for (element: T in this) { accumulator = combine(accumulator, element) } return accumulator }

    七、递归函数 

    Kotlin支持特色功能性编程——尾递归。可以运行算法使用loop循环来代替递归函数,这样可以避免栈溢出。当使用tailrec修饰符时,遇到特定格式,编译器会优化递归,改成快速高效的基于loop循环的版本。示例代码如下:

    tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))

     

    最新回复(0)