Kotlin学习历程——函数与Lambda表达式(一)

Kotlin语言中文站

函数

基础写法

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而言,它可以减少一大堆重载函数。我们来看一个案例:

AndroidEventBus库大家应该都不陌生,在很多业务场景下能实现代码逻辑解耦。如下是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
}

很“高大尚”的一种语法糖,是不是很有意思呢😄。


上一篇:Kotlin学习历程——对象声明与伴生对象
下一篇:Kotlin学习历程——函数与Lambda表达式(二)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hepingdev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值