函数
基础写法
在Kotlin
中使用关键字fun
声明一个函数:
fun printInfo() {
println("This is a function.")
}
如果携带参数
呢?如下main
函数所示:
fun main(args: Array<String>) {
println("length:${args.size}")
}
如果一个函数没有返回值,如上两个函数,那么它的返回值类型默认是Unit
,可省略不写:
我们看看Unit
的源码:
package kotlin
/**
* The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
*/
public object Unit {
override fun toString() = "kotlin.Unit"
}
看注释是说对应Java
中的void
,那就没必要纠结了。
如果有返回值
呢,那就在函数后面写明返回值类型:
/**
* 返回[0,range)范围的随机整数
*/
fun getRandomNumber(range : Int) : Int {
return Random.nextInt(range)
}
/**
* 一个简单的泛型函数
*/
fun <T> getBean(t: T) : T {
return t
}
如果函数的函数体可以由单个表达式(表达式表示有返回值)计算出来,也可以简写成如下形式:
//单个表达式可以计算出来
fun sum(a: Int, b: Int) : Int{
return a + b
}
//可以简写成如下形式, 它和上面的写法是等价的,不过更加简单明了
fun sum(a: Int, b: Int) : Int = a + b
//单个表达式可以计算出来
fun max(a:Int, b:Int) : Int {
if(a > b) {
return a
}
return b
}
//max
fun largeNumber(a:Int, b:Int) : Int = if(a > b) a else b
默认参数
Kotlin
中函数可以有默认值,当省略相应的参数时就会使用默认值;相对Java
而言,它可以减少一大堆重载函数。我们来看一个案例:
Android
中EventBus库大家应该都不陌生,在很多业务场景下能实现代码逻辑解耦。如下是EventBus
的一个消息事件类。
public final class IMessageEvent {
/**
* 此处是各种Message what
* */
public String msg_what;
public String arg1;
public String arg2;
public int arg3;
public int arg4;
public BeBOMessageEvent(String msg_what) {
this.msg_what = msg_what;
}
public BeBOMessageEvent(String msg_what, int arg3) {
this.msg_what = msg_what;
this.arg3 = arg3;
}
public BeBOMessageEvent(String msg_what, String arg1) {
this.msg_what = msg_what;
this.arg1 = arg1;
}
public BeBOMessageEvent(String msg_what, String arg1, int arg3) {
this.msg_what = msg_what;
this.arg1 = arg1;
this.arg3 = arg3;
}
public BeBOMessageEvent(String msg_what, String arg1, String arg2, int arg3) {
this.msg_what = msg_what;
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
}
可以发现重载的构造函数比较多。 如果用Kotlin
来写,将会快捷很多:
class IMessageEvent(var msg_what: String, var arg1: String = "", var arg2: String = "", var arg3: Int = 0, var arg4: Int = 0) {
companion object {
val ENABLE_DEBUG_MODE = "ENABLE_DEBUG_MODE"
}
}
使用如下:
//1个参数,其他全部用默认值
val messageEvent = IMessageEvent(IMessageEvent.ENABLE_DEBUG_MODE)
//2个参数,其他用默认值
val messageEvent1 = IMessageEvent(IMessageEvent.ENABLE_DEBUG_MODE, "A0001")
//或者这样(只传递首尾参数)
val messageEvent2 = IMessageEvent(IMessageEvent.ENABLE_DEBUG_MODE, "A0001", "", 0, 50)
默认参数在某些场景下(一个默认参数在一个无默认值的参数之前),使用上会产生歧义,导致编译报错:
fun printInfo(tag: String = "hepingdev##", info: String) {
println("$tag$info")
}
调用如上函数:
看错误提示是因为没有传递参数值info
,所以这就为难了(我是想第一个参数使用默认值,只传递第二个参数)。
具名参数
在kotlin
中使用具名参数
解决这类问题:
fun main(args: Array<String>) {
printInfo(info = "函数")
}
也就是指明给哪个参数赋值,如上指明给info
参数赋值。
可变数量的参数(vararg)
当方法的参数数据类型已经确定,但是参数的个数不确定,就可以使用可变数量的参数。 如下代码所示:
fun <T> mutableListOf(vararg elements: T): List<T> {
val result = ArrayList<T>()
for (t in elements) // elements is an Array
result.add(t)
return result
}
我们调用上面mutableListOf
函数时,常见场景如:
- 一个一个的传递参数
fun main(args: Array<String>) {
//一个一个的传递参数
var list = mutableListOf<String>("1", "2", "3")
}
- 将一个数组的内容传递给该函数,使用展开操作符(在数组前面加
*
)
//传递一个数组的内容
var aList = arrayOf("1","2","3")
var concatList = mutableListOf("23234", *aList, "w3r")
println(concatList) //打印:[23234, 1, 2, 3, w3r]
它类似JavaScript
里面的展开操作符(…),只是写法不一样。
同样,如果vararg
参数不是列表中最后一个参数,就需要使用具名参数
传递其后的参数值。如下:
fun <T> subList(vararg elements: T, endIndex: Int): List<T>? {
if(elements.isEmpty() || endIndex == 0) return null
val result = ArrayList<T>()
for (e in elements) {
result.add(e)
if(result.size - 1 >= endIndex) {
break
}
}
return result
}
//调用
fun main(args: Array<String>) {
var aList = listOf<String>("1","2","3")
//具名参数endIndex
subList(aList, endIndex = 1)
}
中缀函数
如下代码中until
即中缀函数,调用中缀函数不需要调用的点和圆括号。
for (i in 1 until 5){
println("$i") //1,2,3,4
}
声明一个中缀函数必须满足以下要求:
- 必须是成员函数(对象的方法)或扩展函数。
- 必须只有一个参数,且参数不得是可变数量的参数,同时不能有默认值。
- 必须采用
infix
关键字修饰。
按照上面的要求,我们简单声明两个中缀函数看看,如下:
/* 对象的方法 */
class InfixFunction {
infix fun printInfo(onlyParams : String) {
println(onlyParams)
}
}
/* 调用上面的中缀函数 */
fun main(args: Array<String>) {
val mInfixFunction = InfixFunction()
mInfixFunction printInfo "打印这个值" //打印这个值
}
/* 扩展函数 */
infix fun Int.add_(b : Int) : Int = this + b
/* 调用上面的中缀函数 */
fun main(args: Array<String>) {
val a = 1
val c = a add_ 2
println(c) //3
}
很“高大尚”的一种语法糖,是不是很有意思呢😄。