Kotlin语法基础篇三:函数

前言:

前两篇文章介绍了Kotlin中的基本数据类型属性和控制流。本篇文章我们将介绍Kotlin中比较重要的一个知识点:函数。对于函数,我想每个开发同学都不会陌生。善于将复杂的逻辑拆分成多个功能函数,将对我们代码的可读性和可维护性会有很大的帮助。而将多个复杂的逻辑放在同一个方法中,可能会让代码变得十分臃肿。下面让我们开始本篇文章的学习。

1.函数的声明

在Kotlin中我们用关键字fun来声明一个函数。一个简单的函数声明如下:

kotlin 复制代码
fun sum(left: Int, right: Int): Int {
        return left + right
}

关键字fun后面紧跟着函数名,通常函数名都是以这个函数实现的功能来命名的。函数名后紧跟着小括号(),定义该函数所需要的参数。即name:type。

多个参数用逗号隔开(name:type, name:type)。如果不需要参数,直接用()即可。如果该函数需要返回值则在()后面添加 :type。花括号{ }则代表这个函数的方法体或者说是这个函数的作用域。

2.函数的默认参数

通常在Java中函数我们称之为方法,相比较Java语言,Kotlin中的函数允许有参数默认值。而允许方法的参数可以拥有默认值,可以减少方法的重载(方法名相同,方法的参数类型和个数不同,我们称之为方法的重载)。如下函数的定义:

kotlin 复制代码
fun sum(left: Int, right: Int): Int {
        return left + right
}

// right参数具有默认值0
fun sum(left: Int, center: Int, right: Int = 0): Int {
        return left +center + right
}

当我们给sum函数的参数right添加了默认值以后。在函数调用的地方,我们可以选择性的传或者不传这个参数。

kotlin 复制代码
fun main() {
    sum(0, 10)
    sum(0, 10, 15)
}

fun sum(left: Int, center: Int, right: Int = 0): Int {
    return left +center + right
}

善于使用函数参数的默认值,在实际开发过程中,可以减少像Java语言中的方法重载。

3.具名参数

当我们调用一个拥有众多参数的函数时,参数类型和参数名匹配起来比较麻烦时。具名参数的使用就变得很有意义。使用具名参数可以不用考虑参数在函数中声明的顺序,使用propertyName = propertyValue的方式传入参数。假设我们有如下拥有多个参数的函数fold:

kotlin 复制代码
fun main() {
    fold(right = false, center = "center", left = 0, isEmpty = false)
}

fun fold(left: Int, center: String, right: Boolean, isEmpty: Boolean) {
    // ...省略逻辑
}

fold函数拥有4个参数,当我们在main函数中使用具名参数的方式调用fold函数,我们无需再考虑函数参数在声明时的位置,只要将所有的参数具名传入即可。当然在实际开发的过程中,一个复杂函数的参数远不与此。

4.函数的默认返回值Unit

当一个函数没有返回值时,它将拥有一个默认的返回值类型Unit。通常情况我们都会省略它。如下示例,我们将fold函数的返回值显示的声明成Unit

kotlin 复制代码
fun fold(initValue: Int):Unit {
    // ...省略逻辑
    return Unit
}

// 省略Unit
fun fold(initValue: Int) {
    // ...省略逻辑
    return 
}

返回时,我们可以直接使用return,也可以显示的加上Unit返回值类型。

5.单函数表达式

在上一篇文章属性和控制流中我们介绍到,当if或者when表达式的分支块中仅有一行表达式时,我们可以省略分支块的花括号。而Kotlin中的函数亦是如此。当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可:

kotlin 复制代码
fun sum(left: Int, right: Int): Int = left + right 

// Kotlin编译器可以推断出函数的返回值类型,可省略函数的返回值类型
fun sum(left: Int, right: Int) = left + right 

既然if或者when也可以作为单个表达式,那么我们也可以将一个函数用=连接一个if或者when的表达式。

kotlin 复制代码
fun isEmpty(str:String) = if(str.length == 0) true else false

// 示例代码
fun findNum(num:Int) = when(num) {
    1001 -> 0
    1002 -> 1
    else -> -1
}

6.可变数量的参数

在Java中我们使用propertyType... propertyName的方式来声明一个可变数量的参数:

typescript 复制代码
private void sum(Integer... value) {
        // ...
}

而在Kotlin中我们使用关键字vararg来声明可变数量的参数。

kotlin 复制代码
fun main() {
    sum(1, 2, 3)
}

fun sum(vararg value:Int) {
    for(i in value) {
        println("i = $i")
    }
}

// 输出
i = 1
i = 2
i = 3

7.中缀表示法

在Kotlin中使用infix关键字修饰的函数可以使用中缀表示法,忽略该函数调用时的点和括号。该函数必须满足如下条件:

  • 用infix修饰的函数有且只能有一个参数
  • 必须是成员函数或者扩展函数(关于扩展函数后面会详细讲解)
  • 不能接受vararg声明的可变数量的参数

典型的应用,我们可以看Kotlin中给我们提供的Tuples.kt中的数据类Pair:

kotlin 复制代码
public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable 
// ...

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

// ...

由上面的代码中我们可以看到数据类Pair有使用infix修饰的扩展函数to -> A.to(that: B)。下面我们来看一下在实际开发中的使用:

kotlin 复制代码
fun main() {
    val pair = 20 to "age"
    println("pair = $pair")
}

// 输出
pair = (20, age)

中缀表示法可以让我们的函数调用像阅读英文一样的优雅。使用A to B的方式创建了一个Pair对象,省略了调用函数时的点和括号。下面我们使用infix关键字来实现一个我们自己的定义的函数:

kotlin 复制代码
infix fun <T> Collection<T>.has(item: T) = if (item in this) true else false

fun main() {
    val languageList = arrayListOf("kotlin", "ios", "android")
    if (languageList has "test") {
        println("There is this language")
    } else {
        println("There is no such language")
    }
}

// 输出
There is no such language

8.函数作用域

1.在Kotlin中函数可以在文件顶层声明 。不需要像Java那样要创建一个类来保存一个函数。对与在文件顶层声明的函数默认情况下,我们可以在当前文件所在的项目中任意地方访问,除非你将函数显示的加上private访问修饰符。选中当前项目,右击鼠标或者触摸板。New -> Kotlin Class/File,在弹出的选择框中,我们选择File,声明一个Fun.kt的文件。

kotlin 复制代码
// 当前项目中可以调用
fun sum(left: Int, right: Int): Int {
    return left + right
}

// 当前文件中可以电泳
private fun fold() {
    println("fold called")
}

2.成员函数。

在类内部或者对象内部创建的函数我们称之为成员函数,以点表示法调用。

kotlin 复制代码
class Student {
    fun study() {
        println("I enjoy learning")
    }
}

fun main() {
    Student().study()
}

3.局部函数。(在Kotlin中支持一个函数嵌套另外一个函数)

在函数内部声明一个函数,我们就称这个函数为局部函数。如下示例,我们在main函数的内部声明了一个getMax函数。

kotlin 复制代码
fun main() {
    val a = 100
    val b = 100
    
    // 局部函数
    fun getMax() :Int {
        return if(a > b) {
            println("a = $a")
            a
        } else {
            println("b = $b")
            b
        }
    }

    println("${getMax()}")
}

局部函数可以访问外部函数声明的属性。

9.泛型函数

在Kotlin中我们通常在关键字fun之后紧<T>跟来声明一个泛型函数。(大写字母放在<>中,T是习惯性写法,也可以用别的大写字母表示),如下:

kotlin 复制代码
fun <T> getData(data:T) { 
    println("data = $data")
}

我们也可以将声明的泛型类型作为函数的返回值:

kotlin 复制代码
fun <T> getData(data:T) :T {
    println("data = $data")
    return data
}

关于Kotlin中泛型的使用我们会在后续的文章中详细介绍。

总结

到这里关于Kotlin中函数的介绍我们就写完了,下篇文章我们将详细介绍Kotlin中的高阶函数和Lambda表达式,我们下期再见。

相关推荐
网络研究院23 分钟前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下30 分钟前
android navigation 用法详细使用
android
小比卡丘3 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭4 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss5 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.6 小时前
数据库语句优化
android·数据库·adb
GEEKVIP8 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model200510 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏68910 小时前
Android广播
android·java·开发语言
与衫11 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql