安卓開發(2)—— Kotlin語言概述

Android的官方文件都優先採用Kotlin語言了,學它來進行Android開發已經是一種大勢所趨了。

這裡只講解部分的語法。

如何執行Kotlin程式碼

這裡提供三種方式來執行Kotlin程式碼:

1 使用IDEA來執行。

2 使用線上IDE來執行:https://play.kotlinlang.org/

3 在Android Studio中執行Kotlin程式碼:

在專案中的MainActivity同級目錄下新建一個kotlin檔案就可以直接單獨執行。

例如:在HelloWorld Android專案中

2.2 變數和函式

2.2.1 變數

在Kotlin中變數先分為可變變數和不可變變數,和別的語言不同,沒有那麼多複雜的const使用,只有可變變數和不可變變數。可變變數的關鍵字為var(variable),不可變變數關鍵字為val(value)。

再由通常的程式語言裡面有的型別推導符再分類(相當於就是和給Java/c++等常用的程式語言的變數型別關鍵字的第一個字元變大寫)。

C++ Java Kotlin
int int Int
long long Long
short short Short
float float Float
double double Double
bool boolean Boolean
char char Char
byte byte Byte

在Kotlin中定義一個變數的最完整格式:var/val 變數名 : 變數型別 = xxx

也可以採用自動推導型別來讓Kotlin自動推導變數型別: var/val 變數名 = xxx

//例子
fun main()
{
var a:Int = 10
println("a= " +a)

val b = "hehe"
println(b)
}

2.2.2 函式

Kotlin中的函式關鍵字是fun(function的簡稱)。

Kotlin中定義最標準的函式的模板:

fun 函式名(引數名:引數型別,...引數名n:引數型別) : 返回值型別
{

}

其中函式名自己隨便選,引數有多少個自己也可以隨便定義,如果不想要引數直接寫一個空括號,如果函式不需要返回值也可以直接不寫返回值型別,還可以利用自動推導型別來確定返回值型別。

//例如
fun test(num1:Int,num2:Int):Int
{
return num1+num2
}

如果函式體只有一行程式碼,可以直接寫在函式體定義的尾部,中間用等號連線(返回值不新增return)。例如:

fun test(num1:Int,num2:Int):Int = num1+num2

再加上Kotlin的自動推導,還可以簡化成:

fun test(num1:Int,num2:Int) = num1+num2

2.3 邏輯控制

邏輯控制語句一般有條件語句,迴圈語句來構成。

kotlin中的條件語句主要有兩種方式:if和when。

2.3.1 if條件語句

大體上和C++/Java等程式語言的if-else流程語句一樣,但是Kotlin的if-else語句和C++/Java的程式碼不同的是,if-else語句有返回值。

    var num1 = 10
  var num2 = 20
  var TestNum = if(num1>num2) {
      num1
  }else{
      num2
  }
  println(TestNum)

2.3.2 when條件語句

Kotlin中的when條件語句有點類似與C++/JAVA中的switch語句,但是when語句中拋棄了switch語句中的break,直接作為一次性跳轉使用,不會因為沒有break就繼續向下執行。

格式:

    when(匹配項)
{
匹配值 -> {程式碼邏輯} //如果只有一行程式碼,可以不用加{}
}
//例如:
fun main()
{
  var age = 1
  when(age)
  {
      1 -> println("一歲")
      2 ->{
      println("只有兩歲")
  }
      else -> println("Error")
  }
}

除了精緻匹配匹配項裡的內容外,還可以進行型別匹配:

fun CheckType(num: Number)
{
  when(num)
  {
      is Int -> println("輸入的是Int型別")
      is Double -> println("輸入的是Double型別")
      else -> println("輸入的不是Int或者Double型別")
  }
}
//這裡的Number型別是Kotlin內建的一個抽象類,Kotlin的變數型別都是Number型別的子類,所以可以用它來使用子類,這個相當於
//C++裡面的多型了。
//is是一個關鍵字用來判斷變數的型別,相當於java裡面的instanceof

2.3.3 迴圈語句

kotlin主要提供了while和for迴圈兩種迴圈語句。

while迴圈語句和C++/JAVA/C等語句都一樣,但是在for迴圈語句中有很大的改變。

for迴圈中最主要的是for-in的用法。

在用kotlin中的for-in迴圈時,首先得明白kotlin中的區間的概念,其實就是一個範圍。

可以使用kotlin程式碼來讓某個變數作為一個區間,如:

var test = 0..10

這段程式碼的意思是定義了一個從0到10的左閉右閉區間,預設是

中間每個相差1,其中 ".."是建立兩端閉區間的關鍵字,在".."的兩邊指定區間的左右端點就可以建立一個左閉右閉區間了。

在建立了區間後,就可以使用for-in迴圈來遍歷這個區間了,例如:

fun TestCircle()
{
  val a = 0..10
  for(i in a){
      println(i);
  }
}

還可以建立左閉右開的區間,因為通常在陣列中都是從0開始,比如char[10]的範圍就是0-9的閉區間。

//建立左閉右開區間
var a = 0 until 10
//得到的是一個[0,10)

如果想在迴圈中跳過一些元素,可以使用step關鍵字:

fun TestCircle2()
{
  for(i in 0 until 10 step 2)
  {
      println(i)
  }
}
//表示每次自增2

前面建立的都是從小到大的區間,那麼肯定有要用到從大到小的時候。如果想要建立一個從大到小的就需要新增downTo關鍵字,例如:

fun TestCircle3()
{
  for(i in 10 downTo 1) //這裡就是建立了一個[10,1]的區間,同樣也可以採用step來跳過一些
  {
      println(i)
  }
}

2.4 Kotlin面向物件程式設計

Kotlin同樣也是一門可以面向物件的語言。

新建類有兩種辦法,一種是直接利用Android Studio IDE來建立,還有一種是直接原始碼建立。

利用IDE建立:

右鍵想要在那個包裡面建立->New->Kotlin File/Class: (再在這裡輸入類名)

直接原始碼建立:

使用類的關鍵字class直接定義就好了,類的屬性可以在函式體裡展示,也可以在類的內部展示

//例
class Test(var num1:Int,var num2:Int)
{
var num3 = (num1+num2)*2
}
//這就寫好了一個很簡單的類

例項化類,用類來建立物件,就等於把類當作一個變數型別來使用就好了,就像Int,Double一樣。

//例項化:
var TestClass = Test(1,2)//這樣就是例項化了一個Test類的物件
//使用類和物件的例項:
class a
{
  var name = "test"
}
fun TestClass()
{
  var Test = a()
  println(Test.name)
}

2.4.2 繼承和建構函式

在Kotlin中的繼承和別的面向物件語句繼承不一樣。

Kotlin裡面的類預設是不可繼承的(抽象類除外),如果想要類可以被繼承,需要在建立的時候新增OPEN關鍵字,例如:

open class Person
{
...
}
//加上了open關鍵字後,這個類就可以被繼承了。

繼承首先得需要了解Kotlin裡面的建構函式,每個Kotlin中的類有一個預設的建構函式和C++一樣,這個建構函式不需要寫,只需要在例項化的時候將建立類的時候申明的成員也加上去,但是在類的主體中的成員就不需要添加了。

相當於這個預設的主建構函式就是根據申明時的成員將其賦值給類建立的物件。

//例:
class TestClass(var num1:Int,var num2:Int)
{
  var num3 = num1 + num2;
  fun TestClassPrint()
  {
      println(num1)
      println(num2)
      println(num3)
  }
}
fun TestClassFun()
{
  var Test= TestClass(1,2)
  Test.TestClassPrint()
}

繼承:在繼承時首先需要要繼承的該類申明時有OPEN關鍵字,然後直接在定義的子類的時候加上: 和父類的建構函式就好了,和C++一樣的。

class Person()
{

}

class Person2 : Person()
{

}

2.4.3 介面

這個就和JAVA中的介面差不多了,同樣也和C++裡面的虛基類類似。

首先建立一個介面類:

interface study
{
  fun ReadBooks()
  fun DoHomeWork()
}

接下來就可以用子類來重寫實現了:

class Student : Study
{
  override fun ReadBooks()
  {
      println("學生正在看書")
  }
  override fun DoHomeWork()
  {
      println("學生正在做作業")
  }
}
//重寫介面類的函式需要新增override關鍵字

還可以在介面類中寫預設函式,也就是將一個函式實現,那麼接下來繼承介面類的類可以選中不實現該函式,但是沒有實現的介面類函式就必須要實現。

//例如:
interface study
{
  fun ReadBooks()
  {
  println("看書中")
  }
  fun DoHomeWork()
}

2.4.4 成員屬性

每門面向物件語言都會有成員屬性修飾符,Kotlin也不例外,Kotlin有public,private,protected和internal四種。

屬性 作用
public Kotlin中預設是public,public表示對所有都可見
private 只有當前類可見
protected 對當前類,子類和包路徑下的類看郵件
internal 同一模組中的類可見

2.4.5 資料類和單例類

資料類,在建立後,會自動生成很多和資料相關的函式,比如計算hash值的hashcode,比如判斷是否相等,例如:

data class CellPhone(var brand:String,var price:Double)
fun TestBase()
{
  var test1 = CellPhone("test1",1.11)
  var test2 = CellPhone("test2",2.22)
  println("CellPhone1 等於 CellPhone2 是真的嗎?" + (test1 == test2))
}

單例類:單例類只能建立一個物件,藉此來避免建立多個物件。

在別的C++/JAVA等語言或許會比較麻煩,但是Kotlin非常的遍歷,只需要在建立類前新增關鍵字object就好了,例:

object SingClassTest()
{
fun Test()
{
println("test")
}
}

2.5 Lambda程式設計

Lambda的定義是:一小段可以作為引數傳遞的程式碼。(類似與C裡面的巨集定義)

//語法結構
{引數名1:引數型別,引數名2:引數型別 -> 函式體}
//函式體可以寫任意多少行程式碼
//最後一行程式碼會作為返回值

2.5.1 集合的建立與使用

類似於C++的STL一樣,就好比是Kotlin內建的一些類。類似於C++的STL一樣,就好比是Kotlin內建的一些類。

//在java中
val list = ArrayList<String>()
list.add("test")

//c++
vector<int> a;
a.push_bak(1);

//Kotlin提供內建的listOf()函式來初始化集合
val list = listOf("test1","test2")
//for-in語句不僅僅可以用在迴圈,還可以用在集合這裡。

但是需要注意的是listOf建立的集合是不可變的,只能讀取,不能修改刪除,新增等操作。

建立可變的集合:使用mutableListOf()函式來建立就好了。就可以使用add()等等操作了。

fun TestLamba()
{
  val list = mutableListOf("Apple","Banana","Potato")
  list.add("hehe")
  for(i in list)
  {
      println(i)
  }
}

前面寫的是list列表集合,set無序集合和list列表集合使用辦法一樣。

還有Map鍵值對集合,Map是一種資料結構的內容。

//使用辦法
  val map = HashMap<String,Int>()
  map.put("apple",1)
  map.put("banana",2)
  map.put("orange",3)
//可以用put()和get()方法來新增和獲取
//還可以直接使用類似於陣列下標操作來處理
var test = map["apple"]
map["apple"] = 1000

同樣map也有初始化函式mapOf()和mutableMapOf()來簡化map的初始化。

2.5.2 集合的函式API

相當於各種內建的Lambda的類裡面有公用的API函式來使用,和STL是一樣一樣的。

例如:

//在一個水果集合裡面找到單詞最長的那個
var list = listOf("apple","banana","pear","Watermelon")
val maxLengthFruit = list.maxBy{it.length}
//這個一個由lambda表示式簡化過來的版本
//接下來由繁入簡來講述這個API

看最原始的版本:

var list = listOf("apple","banana","pear","Watermelon")
val lambda = {fruit:String -> fruit.length}
val maxLengthFruit = list.maxBy({lambda})
//maxBy這個函式根據傳入的引數來確定遍歷集合的方式

優化1:不需要單獨的lambda變數

var list = listOf("apple","banana","pear","Watermelon")
val maxLengthFruit = list.maxBy{fruit:String -> fruit.length}

優化2:在Kotlin中,當Lambda引數是函式的最後一個引數時,可以把lambda表示式單獨用{}獨立出來:

var list = listOf("apple","banana","pear","Watermelon")
val maxLengthFruit = list.maxBy(){fruit:String -> fruit.length}

優化3:如果Lambda引數是函式的唯一一個引數,還可以將函式外的括號省略

var list = listOf("apple","banana","pear","Watermelon")
val maxLengthFruit = list.maxBy{fruit:String -> fruit.length}

優化4:當lambda表示式的引數列表只有一個引數時,也不必宣告引數,可以直接用it關鍵字代替(也就是代替它傳進來的)

var list = listOf("apple","banana","pear","Watermelon")
val maxLengthFruit = list.maxBy{it.length}