第七章 (一)類.md
類
1.定義
[修飾符] class 類名 [constructor 主構造器]{
0~N個次構造器
0-N個屬性
0-N個方法
}
空類:沒有類體,可以省略大括號
如:class EmptyClass
1.1、修飾符
類修飾符: public、internal、private(只能出現其一),final、Open、abstract(只能出現其一)
構造器修飾符: public、protected、internal、private
2、構造器
格式:
[修飾符] constructor(形參列表){
}
修飾符:可以省略,也可以是public、protected、internal、private其中之一
分為主構造器和次構造器,一個類可以有01個主構造器,0N個次構造器
主構造器:緊跟在類名後,
- 使用關鍵字"constructor"
- 無執行體,但可以有多個形參,可以在屬性宣告、初始化塊中使用
- 如果構造器沒有任何修飾符或註解可以省略"constructor"關鍵字
如:
class Person constructor(age:int,name:String){
}
主構造器的引數,可以在屬性宣告、初始化塊中使用;
如果沒有為非抽象類提供任何主、次構造器,系統預設會提供一個無參的主構造器,預設修飾符public;但是一旦程式設計師為類提供了一個構造器,系統將不會為類提供預設構造器
3、屬性
Kotlin中的屬性相當於java中的欄位(成員變數)、setter()、getter()方法 格式:
[修飾符] var|val 屬性名:型別=[預設值]
[getter方法]
[setter方法]
修飾符可以使public|protected|internal|private、final|open|abstract兩部分都只能出現其一
關於函式多說一點:如果是定義在類中的函式,可以使用以上修飾符修飾,但是直接定義在.kt檔案中(類外面)的頂級函式,不能使用protected、abstract|fianl修飾
定義val(只讀欄位),系統會為它生成public final修飾的getter方法,定義var欄位,會自動生成getter和setter方法;這些成員屬性變數,需要程式設計師顯示指定初始值,要麼在定義時指定初始值,要麼在構造器中指定初始值,Kotlin中定義的屬性相當於java中private修飾的field.
3.1、自定義getter、setter方法
在定義屬性時,可以指定自定義的getter、setter方法,在這些方法中加入自己的控制邏輯; getter方法:是形如get(){}方法,無參、待返回值
setter方法:是一個形如set(value){}的方法,帶一個引數、無返回值的方法
自定義getter、setter方法無須使用fun關鍵字
如:
class User {
var first:String="lin"
var last:String="leslie"
val fullName:String
get() = "${first}.${last}"
}
這裡對只讀fullName重寫了了getter方法,因此該屬性沒有幕後欄位(下面就會講到),Kotlin不允許為該屬性指定初始值。該屬性是通過上面兩個屬性計算出來的,Kotlin不需要為它生成對應的feild,他不需要真正的儲存狀態;
如果只需要改變getter或者setter方法的可見性或者對其添加註解,不需要改變其預設實現,可以自定義getter或者setter方法名,而不用重新定義其程式碼實現;
如:
class User{
var foo:String="abc"
private set
var bar:Int?=null
@inject set
}
3.2、幕後欄位
普通屬性,kotlin會生成一個field(欄位)、setter()(只讀屬性沒有)、getter()方法,生成的field就叫做幕後欄位,Kotlin要求為該屬性顯示指定初始值,要麼在定義時就指定,要麼在構造器中指定; 如果沒有幕後欄位,則不允許為該屬性指定初始值(因為沒有field,沒有地方儲存)
那些時候會為屬性生成幕後欄位呢?
- 只讀屬性必須重寫getter()方法,讀寫屬性必須重寫setter()、getter()方法,否則會為該屬性生成幕後欄位
- 重寫getter()或者setter()方法時 使用field關鍵字引用幕後欄位
3.3、屬性延遲初始化
Kotlin要求所有屬性必須顯示初始化,前面我們說了 要麼在宣告時初始化,要麼在構造器中初始化。但有時候,這不是必須的。如通過依賴注入為屬性初始化,或者在單元測試的setUp()方法初始化
通過使用"lateinit"修飾符修飾屬性,延遲初始化(就可以不在定義屬性或構造器中初始化)
但對可以使用"lateinit"修飾符修飾的屬性有要求:
- lateinit只能修飾類體中的宣告的可變屬性(val宣告的屬性不行,在主構造器中宣告的屬性也不行)
- 修飾的屬性不能有自定義的setter()或者getter()方法
- 屬性必須是非空型別(不能是String?這種型別)
- 屬性不能是原生型別(即Java8對應的8種基本型別對應的型別)
Kotlin不會像Java為屬性預設初始化,一旦在賦初始值前訪問該屬性,就會報"延遲屬性還未初始化異常"
3.4、內聯屬性
說內聯屬性之前,我們可以先回憶一下行內函數:
高階函式:(為函式傳入函式或者lambda表示式作為引數)
其呼叫過程:
- 程式將執行順序轉移到被呼叫函式或者lambda表示式所在的記憶體地址
- 當被呼叫的表示式或者函式執行完後,再回到原函式執行的地方
行內函數:使用inline關鍵字修飾帶函式形參的函式即可;其實質就是講被呼叫函式或者Lambda表示式函式體程式碼複製貼上到呼叫函式中
內聯屬性要求:
- 該屬性沒有幕後欄位
可以修飾屬性的getter或者setter方法,或者修飾屬性本身(表示同時修飾setter、getter方法)
和行內函數一樣,在執行getter或者setter方法是會執行內聯化
方法
Kotlin中方法和函式區別:
方法:指定定義在類中的函式 函式:
方法修飾符:public、protected、internal、private、final、abstract、open
函式修飾符:不能使用protected、abstract、final修飾
資料類
Kotlin提供的一種特殊的類,專門用於封裝資料。