Kotlin基礎之函式

weixin_34185364發表於2018-04-22

函式的基本格式

fun 函式名(引數名:引數型別):返回值型別

說明:

  • 函式的宣告使用 fun 關鍵字
  • 函式的呼叫與Java無異 物件.方法名(引數)
  • 無返回值型別使用 Unit 表示,允許省略
  • 函式修飾符預設是public,所以無public修飾
  • 重寫的方法是:overrite fun 函式名(引數名:引數型別):返回值型別
定義函式

以下是定義函式的幾種樣式:

  • 定義無引數,無返回值的函式(表示無返回值的 Unit被省略了)

      fun init(){
          //函式體
      }
    
  • 定義無引數,無返回值的函式( Unit:類似Java中的void)

      fun get() : Unit{
          //函式體
      }
    
  • 定義無引數,返回值為String型別的public方法

     fun get() : String{
         //函式體
         return "你好"
     }
    
  • 定義 有引數,返回值為String型別的public方法

      fun get(str:String) : String{
          //函式體
          return "你好"
      }
    
  • 定義有引數,無返回值(引數1帶問號,表示str引數可以是空值)

      fun set(str : String ?,int : Int,arr :Array<String>){
          //語句體
      }
    
  • 將表示式作為函式體、返回值型別自動推斷的函式

      fun sun(a:Int,b:Int) = a+b
    
基本格式-引數的幾種形式
  • 預設引數

預設引數:在定義函式時直接指定引數的預設值,
格式:引數名:引數型別 = 引數預設值
書寫及呼叫如下

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    //注意呼叫的時候沒有給引數
    Log.i(tag,get())//輸出結果:你好--Kotlin
    //提供引數值,則覆蓋引數的預設值
    Log.i(tag,get("hello world"))//輸出結果:hello world--Kotlin
}
/**
 * 有引數,返回值為String型別的public方法
 */
fun get(str:String = "你好") : String{
    //函式體
    return str+"--Kotlin"
}

通過以上程式碼可以看到當函式是有預設引數的,那麼呼叫時可以不給引數;給參則覆蓋引數的預設值

  • 命名引數

命名引數:呼叫時更換預設引數的值

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /**
         輸出結果:除了int外都是預設的引數
        Int型別引數值是:1
        String型別引數值是:你好
        Char型別引數值是:a
        Boolean型別引數值是:true
         */
        Log.i(tag,get1(1))

        /**
        輸出結果:除了int外,Boolean 型別的引數發生了改變,呼叫方法時flag = false既是命名引數
        Int型別引數值是:1
        String型別引數值是:你好
        Char型別引數值是:a
        Boolean型別引數值是:false
         */
        Log.i(tag,get1(1,flag = false))
    }

    /**
     * 有引數,返回值為String型別的public方法
     */
    fun get1(int :Int ,str:String = "你好",char :Char = 'a', flag :Boolean = true) : String{
        //函式體
        return "Int型別引數值是:$int\nString型別引數值是:$str\nChar型別引數值是:$char\nBoolean型別引數值是:$flag"
    }
  • 可變引數

某種型別的引數數量是不確定的,關鍵字vararg修飾
格式:vararg str :String 表示String型別的引數是不固定的
可變引數在使用時當做一個陣列
函式的引數不能出現2個vararg以上
可變引數的型別可以是基本型別、陣列、容器

可變引數是基本型別,以Int為例

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    Log.i(tag,get2(1,3,4))//輸出結果:Int型別引數值是: 1, 3, 4,
}

/**
 * 有引數,是可變引數
 */
fun get2(vararg int :Int ) : String{
    var str = ""
    for(it in int){
        str =  "$str $it,"
    }
    return "Int型別引數值是:$str"
}

可變引數是陣列型別,以Array<Int>為例

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    /**
    輸出結果:
    第1個引數陣列的元素是:{ 1, 2, 3,}
    第2個引數陣列的元素是:{ 11, 22, 33,}
    第3個引數陣列的元素是:{ 111, 222, 333,}
     */
    Log.i(tag,get3(arrayOf(1,2,3), arrayOf(11,22,33), arrayOf(111,222,333)))

}
/**
 * 可變引數為陣列型別
 */
fun get3(vararg arrs :Array<Int> ) : String{
    var count = 1
    var t = ""
    for(it in arrs){
        //此時it表示的是一個陣列引數
        var str = ""
        for(i in it){
            //此時i表示的是一個陣列引數中的一個元素
            str =  "$str $i,"
        }
        var s = "第${count}個引數陣列的元素是:{${str}}\n"
        count++;
        t = t +s
    }
    return t
}

可變引數是容器之佇列,以List<String>為例

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    /**
    輸出結果:
    第1個引數陣列的元素是:{ 1q, 2q, 3q,}
    第2個引數陣列的元素是:{ 11q, 22q, 33q,}
    第3個引數陣列的元素是:{ 111q, 222q, 333q,}
     */

    Log.i(tag,get4(listOf("1q","2q","3q"), listOf("11q","22q","33q"), listOf("111q","222q","333q")))

}

/**
 * 可變引數是List<String>
 */
fun get4(vararg arrs :List<String> ) : String{
    var count = 1
    var t = ""
    for(it in arrs){
        //此時it表示的是一個佇列引數
        var str = ""
        for(i in it){
            //此時i表示的是一個陣列引數中的一個元素
            str =  "$str $i,"
        }
        var s = "第${count}個引數陣列的元素是:{${str}}\n"
        count++;
        t = t +s

    }
    return t
}

特殊函式

  • 泛型函式
  • 行內函數
  • 簡化函式
  • 尾遞迴函式
  • 高階函式
泛型函式

定義泛型函式格式:fun <T>函式名(引數名:T){}
泛型函式可以定義在類的外面,是一個全域性函式。

行內函數

定義行內函數格式:inline fun <reified T : Number>函式名(引數名:T){}
行內函數編譯的時候回再呼叫處把該函式的內部程式碼直接賦值一份,呼叫幾次就會複製幾次(考慮記憶體洩漏)
Kotlin中要求引數型別完全匹配(子父類,實現類都不可以的)

/**
 * 行內函數:有點引數傳遞的是父類,呼叫的時候給引數是子類
 * 因為Kotlin要求引數型別完全匹配
 */
inline fun <reified T : Number>  sum (array : Array<T>) : String{
    var str = ""
    for(it in array){
        str =  "$str $it,"
    }
    return str;
}

class MainActivity : AppCompatActivity() {
    val tag = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.i(tag,sum(arrayOf(1,2,3,4,5)))
        Log.i(tag,sum(arrayOf(1.0,2.0,3.0,4.0,5.0)))
    }
}
簡化函式

格式: fun 函式名(引數名:引數型別):返回值型別 = 函式體
函式體比較簡單的時候

fun sum(a : Int ,b : Int) :Int = if(a >= 0 && b >= 0) a+b else Math.abs(a)+Math.abs(b)
尾遞迴函式

尾遞迴函式:函式末尾的返回值重複呼叫了自己
格式:tailrec fun 函式名(引數名:引數型別):返回值型別{}
tailrace:告訴編譯器是尾遞迴函式,編譯器會相應的優化的

高階函式

高階函式:函式B的引數中包含另一個函式A,那麼函式B就是高階函式,函式A成為高階函式的函式引數

增強系統函式

  • 擴充套件函式
  • 擴充套件高階函式
  • 日期時間函式
  • 單例物件
擴充套件函式
擴充套件高階函式
日期時間函式
單例物件

參考資料:《Kotlin從零到精通-Android開發》
Demo地址:https://github.com/sexyhair79/demokotlinBasics

相關文章