kotlin中函數(shù)的使用和聲明與java中大部分都是相同的慌闭,本文只針對(duì)某幾個(gè)點(diǎn)作出一些自己的理解电抚。
類外聲明函數(shù)
不同于java函數(shù)依賴于class,kotlin中的函數(shù)在編譯過(guò)程中依賴的是package,所以可以將函數(shù)聲明在class外,減少了一些輔助性函數(shù)與class的耦合镊叁。
class A{
//...
}
fun outClass(){//這樣做的方式是完全合法的
//....
}
命名參數(shù)
java中我們常常見到public void X(param1,param2,param3...paramN){}
這種參數(shù)很多的函數(shù)尘颓,寫起來(lái)比較麻煩走触,kotlin中使用命名參數(shù)可以有效的減少代碼量
fun nameParamsTest(str: String,
booleanValue: Boolean = false,
intValue: Int = 1,
doubleValue: Double = 1.0){
//do nothing
LogUtils.v(TAG,"$str boolean = $booleanValue int = $intValue double = $doubleValue")
}
如上聲明的函數(shù)在聲明時(shí)使用了默認(rèn)值,在使用中如果不需要改變默認(rèn)值則可以用下面的方式進(jìn)行調(diào)用
nameParamsTest("aaa",doubleValue = 2.0)//aaa boolean = false int = 1 double = 2.0
nameParamsTest("bbb",intValue = 2)//bbb boolean = false int = 2 double = 1.0
可變數(shù)量參數(shù) vararg
使用vararg關(guān)鍵字修飾的參數(shù)疤苹,可以將其看為是一個(gè)可變長(zhǎng)度的數(shù)組互广。它修飾的參數(shù)最好放在參數(shù)列表的最后,如果把它后面還有其他參數(shù)卧土,則需要使用命名參數(shù)的語(yǔ)法對(duì)后面的參數(shù)進(jìn)行傳遞惫皱,如下:
/**
* 可變數(shù)量的參數(shù)
* @param list
* @param values 這里的values可以看做是一個(gè)數(shù)組即 values: Array<out T>,
* 一般來(lái)說(shuō)尤莺,arrarg傳遞可變數(shù)量參數(shù)應(yīng)放置在參數(shù)列表的最后旅敷,
* 如果不是的話,它之后的參數(shù)應(yīng)該用命名參數(shù)的方式進(jìn)行傳遞,具體參見 [appendList2]
*/
fun <T> appendList(list: MutableList<T>, vararg values: T): List<T>{
list += values
for (i in list.indices){
LogUtils.v(TAG,"i = ${list[i]}")
}
return list
}
fun <T> appendList2(vararg values: T,list: MutableList<T>): List<T>{
list += values
for (i in list.indices){
LogUtils.v(TAG,"i = ${list[i]}")
}
return list
}
調(diào)用時(shí)
appendList(ArrayList<Int>(),1,2,3,4)
appendList2(5,6,7,8,list = ArrayList<Int>())//如果這里把list=去掉颤霎,則無(wú)法通過(guò)編譯
在給vararg
修改時(shí)的參數(shù)傳參時(shí)媳谁,我們可以用*Array
將數(shù)組中的數(shù)據(jù)當(dāng)做參數(shù)傳遞涂滴,而不是傳遞數(shù)組對(duì)象。
val array = intArrayOf(1, 2, 3)
appendList(ArrayList<Int>(),*array )
尾遞歸 tailrec
如果函數(shù)的最后一個(gè)操作是它本身晴音,我們可以將一個(gè)for循環(huán)改寫為類遞歸的方式柔纵,避免指針越界。這就是尾遞歸锤躁。尾遞歸函數(shù)在聲明時(shí)需要使用關(guān)鍵字tailrec 搁料,注意如果最后一個(gè)操作是放置在try-catch模塊中,我們不能保證最后一個(gè)操作能夠順利進(jìn)行系羞,所以不能使用尾遞歸簡(jiǎn)寫代碼郭计。如下,我們將taiRec2()
可以改寫為tailRec()
/**
* 尾遞歸
* 如果函數(shù)將其自身調(diào)用作為最后一個(gè)操作時(shí)椒振,可以使用如下的方式拣宏,將一個(gè)for循環(huán)改寫為一個(gè)類似遞歸的寫法
* 因?yàn)檫@個(gè)特性,他不能放在try-catch模塊中
* 它的功能和[taiRec2]是一致的
*/
tailrec fun taiRec(x: Double = 1.0): Double
= if (x == Math.cos(x)) x else taiRec(Math.cos(x))
private fun taiRec2(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (x == y) return y
x = y
}
}