函數的定義與調用

一、在kotlin中建立集合


kotlin沒有本身專門的集合類,而是採用的java的集合類,不過書寫方式不同。java

val set=hashSetOf(1,7,53) //對應hashset
val list=arrayListOf(1,7,53)   //ArrayList
val map=hashMapOf(1 to "one",7 to "seven",53 to "fifty-three")//HashMap

不過kotlin有本身新增的方法:last(),max()集合中最後一個元素和最大的元素。正則表達式

二、讓函數更好調用


java的集合都有一個默認的toString()實現,可是它的輸出格式是固定的。後端

val list=listOf(1,2,3)//listOf對應的是(Arrays內部類ArrayList)
println(list)
結果:[1,2,3]

上面的結果是固定格式的,默認實現了toString().api

fun <T> joinToString(collection:Collection<T>,separator:String,prefix:String,postfix:String):String{
    val result=StringBuilder(prefix)
    for((index,element) in collection.withIndex()){
    if(index>0) result.append(separator)
    result.append(element)
    }
    result.append(postfix)
    return result.toString()
}
val list=listOf(1,2,3)
println(joinToString(list,"; ","(",")"))
結果:(1;2;3)

當咱們想要改變集合輸出格式的時候能夠自定義,像上面這樣:逗號變分號。數組

2.1 命名參數

在上面的例子中,咱們單看這一句joinToString(list,"; ","(",")")會發現咱們必需要找到上面對應的函數聲明才能更好的理解咱們寫的是啥。
爲了解決這個問題,kotlin引出了命名參數:當調用一個kotlin自定義的函數時,能夠顯式地標明一些參數的名稱。app

joinToString(list,separator=";",prefix="(",postfix=")")

2.2 默認參數值

在聲明函數的時候,指定參數的默認值,能夠避免建立重載的函數。函數

fun <T> joinToString(collection:Collection<T>,separator:String,prefix:String,postfix:String):String

當你調用的時候能夠用全部參數來調用這個函數,也能夠省略掉部分參數。post

三、擴展函數和屬性


Kotlin 能夠對一個類的屬性和方法進行擴展,且不須要繼承或使用 Decorator 模式。
擴展是一種靜態行爲,對被擴展的類代碼自己不會形成任何影響。ui

3.1 導入和擴展函數

擴展函數能夠在已有類中添加新的方法,不會對原類作修改.
擴展函數定義形式:this

fun receiverType.functionName(params){
    body
}
  • receiverType:表示函數的接收者,也就是函數擴展的對象
  • functionName:擴展函數的名稱
  • params:擴展函數的參數,能夠爲NULL
    如下實例擴展 User 類 :
class User(var name:String)

/**擴展函數**/
fun User.Print(){
    print("用戶名 $name")
}

fun main(arg:Array<String>){
    var user = User("Runoob")
    user.Print()
}
實例執行輸出結果爲:
用戶名 Runoob

下面代碼爲 MutableList 添加一個swap 函數:

// 擴展函數 swap,調換不一樣位置的值
fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1]     //  this 對應該列表
    this[index1] = this[index2]
    this[index2] = tmp
}

fun main(args: Array<String>) {

    val l = mutableListOf(1, 2, 3)
    // 位置 0 和 2 的值作了互換
    l.swap(0, 2) // 'swap()' 函數內的 'this' 將指向 'l' 的值

    println(l.toString())
}
實例執行輸出結果爲:
[3, 2, 1]

3.2 不可重寫的擴展函數

擴展函數是靜態解析的,並非接收者類型的虛擬成員,在調用擴展函數時,具體被調用的的是哪個函數,由調用函數的的對象表達式來決定的,而不是動態的類型決定的:

open class C

class D: C()

fun C.foo() = "c"   // 擴展函數 foo

fun D.foo() = "d"   // 擴展函數 foo

fun printFoo(c: C) {
    println(c.foo())  // 類型是 C 類
}

fun main(arg:Array<String>){
    printFoo(D())
}
實例執行輸出結果爲:
c

若擴展函數和成員函數一致,則使用該函數時,會優先使用成員函數。

class C {
    fun foo() { println("成員函數") }
}

fun C.foo() { println("擴展函數") }

fun main(arg:Array<String>){
    var c = C()
    c.foo()
}
實例執行輸出結果爲:
成員函數

3.3 擴展屬性

除了函數,Kotlin 也支持屬性對屬性進行擴展:

val <T> List<T>.lastIndex: Int
    get() = size - 1

擴展屬性容許定義在類或者kotlin文件中,不容許定義在函數中。初始化屬性由於屬性沒有後端字段(backing field),因此不容許被初始化,只能由顯式提供的 getter/setter 定義。

val Foo.bar = 1 // 錯誤:擴展屬性不能有初始化器

擴展屬性只能被聲明爲 val。

四、可變參數、中綴調用和庫的支持


4.1 擴展java集合的API

fun <T> List<T>.last():T//返回最後一個元素
fun Collection<Int>.max():Int//返回集合中的最大值

爲何kotlin用的是java的集合,卻能給它添加本身又增長的方法?
函數last和max都被聲明成了擴展函數。

4.2 可變參數:讓函數支持任意數量的參數

可變參數的關鍵字vararg,能夠用來聲明一個函數將可能有任意數量的參數
fun listOf (vararg values:T):List {...}
kotlin庫中是這樣定義listOf()函數的,正由於這樣咱們調用它時才能夠傳遞任意個數的參數給它
kotlin和java的另外一個區別是:當須要傳遞的參數已經包裝在數組中時,調用該函數的語法。
在java中能夠按原樣傳遞數組,kotlin要求你顯式地解包數組。這個叫作展開運算符,在參數前面加*

fun main(args:Array<String>){
    val list=listOf("args: ",*args)
    println(list)
}

4.3 鍵值對的處理:中綴調用和重構聲明

val map=mapOf(1 to "one",7 to "seven",53 to "fifty-three")

這行代碼中的單詞to不是內置結構,而是一種特殊的函數調用,被稱爲中綴調用。

重構聲明:
中綴調用能夠與只有一個參數的函數一塊兒使用,不管是普通的函數仍是擴展函數。要容許使用中綴符合調用函數,須要使用infix修飾符來標記它。

infix fun Any.to(other:Any)=Pair(this,other)

咱們能夠直接用Pair的內容來初始化兩個變量。
val (number,name)=1 to "one"
這個功能稱爲解構聲明。

五、字符串和正則表達式的處理


5.1 分割字符串

println("12.345-6.A".split("\\.|-".toRegex()))
結果:[12,345,6,A]

kotlin提供了一些名爲split的,具備不一樣參數的重載的擴展函數。用來承載正則表達式的值須要一個Regex類型,而不是String。上面例子中就是使用擴展函數toRegex將字符串轉換爲正則表達式。
可是對於一些簡單的狀況,不須要使用正則表達式。kotlin中的split擴展函數的其餘重載支持任意數量的純文本字符串分隔符:

println("12.345-6.A".split(".","-"))
[12,345,6,A]

5.2 正則表達式和三重引號的字符串

咱們解析一個文件路徑:/Users/yole/kolin-book/chapter.doc
①使用String的擴展函數來解析文件路徑

fun parsePath(path:String){
    val directory=path.substringBeforeLast("/")
    val fullName=path.substringAfterLast("/")
    val fileName=fullName.subStringBeforeLast(".")
    val extension=fullName.subStringAfterLast(".")
    println("Dir:$directory,name:$fileName,ext:$extension")
}
parsePath("/Users/yole/kolin-book/chapter.doc")
結果:Dir:Users/yole/kolin-book,name:chapter,ext:doc

②使用正則表達式來解析文件路徑

fun parsePath(path:String){
    val regex="""(.+)/(.+)\.(.+)""".toRegex()
    val matchResult=regex.matchEntire(path)
    if(matchResult!=null){
        val (directory,filename,extension)=matchResult.destructured
        println("Dir:$directory,name:$fileName,ext:$extension")
    }
}

三重引號字符串不須要對任何字符進行轉義。第一個(.+)包含最後一個斜線前的字串。第二個包含最後一個點前的字串,第三個包含剩餘部分。

5.3 多行三重引號的字符串

三重引號字符串不只能夠避免轉義字符,並且它能夠包含任意字符,包括換行符。並且它提供了一種簡單的方法把包含換行符的文本嵌入到程序中。

val kotlinLogo="""| //
                 .|//
                 .|/ \"""
println(kotlinLogo.trimMargin("."))
結果: | //
      |//
      |/ \
相關文章
相關標籤/搜索