1. 程式人生 > >第七章 (一)類.md

第七章 (一)類.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個次構造器

主構造器:緊跟在類名後,

  1. 使用關鍵字"constructor"
  2. 無執行體,但可以有多個形參,可以在屬性宣告、初始化塊中使用
  3. 如果構造器沒有任何修飾符或註解可以省略"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,沒有地方儲存)

那些時候會為屬性生成幕後欄位呢?

  1. 只讀屬性必須重寫getter()方法,讀寫屬性必須重寫setter()、getter()方法,否則會為該屬性生成幕後欄位
  2. 重寫getter()或者setter()方法時 使用field關鍵字引用幕後欄位

3.3、屬性延遲初始化

Kotlin要求所有屬性必須顯示初始化,前面我們說了 要麼在宣告時初始化,要麼在構造器中初始化。但有時候,這不是必須的。如通過依賴注入為屬性初始化,或者在單元測試的setUp()方法初始化

通過使用"lateinit"修飾符修飾屬性,延遲初始化(就可以不在定義屬性或構造器中初始化)

但對可以使用"lateinit"修飾符修飾的屬性有要求:

  1. lateinit只能修飾類體中的宣告的可變屬性(val宣告的屬性不行,在主構造器中宣告的屬性也不行)
  2. 修飾的屬性不能有自定義的setter()或者getter()方法
  3. 屬性必須是非空型別(不能是String?這種型別)
  4. 屬性不能是原生型別(即Java8對應的8種基本型別對應的型別)

Kotlin不會像Java為屬性預設初始化,一旦在賦初始值前訪問該屬性,就會報"延遲屬性還未初始化異常"

3.4、內聯屬性

說內聯屬性之前,我們可以先回憶一下行內函數:

高階函式:(為函式傳入函式或者lambda表示式作為引數)

其呼叫過程:

  1. 程式將執行順序轉移到被呼叫函式或者lambda表示式所在的記憶體地址
  2. 當被呼叫的表示式或者函式執行完後,再回到原函式執行的地方

行內函數:使用inline關鍵字修飾帶函式形參的函式即可;其實質就是講被呼叫函式或者Lambda表示式函式體程式碼複製貼上到呼叫函式中

內聯屬性要求:

  1. 該屬性沒有幕後欄位

可以修飾屬性的getter或者setter方法,或者修飾屬性本身(表示同時修飾setter、getter方法)

和行內函數一樣,在執行getter或者setter方法是會執行內聯化

方法

Kotlin中方法和函式區別:

方法:指定定義在類中的函式 函式:

方法修飾符:public、protected、internal、private、final、abstract、open

函式修飾符:不能使用protected、abstract、final修飾

資料類

Kotlin提供的一種特殊的類,專門用於封裝資料。