* 在Java中可以聲明一個或多個構造方法。Kotlin也是一樣的,只是做了一點修改:
* 區分了 主構造方法(通常是主要而簡潔的初始化類的方法,並且聲明在類外部聲明)和 從構造方法(在類的內部聲明)
* 同樣也允許在初始化語句塊中添加額外的初始化邏輯。
/** * 這里被括號圍起來的語句塊就叫做“主構造方法”,它的目的有兩個: * 表明構造方法的參數,以及定義使用這些參數的初始化的屬性 */ class User(val username: String)
下面的類聲明是上面類聲明的完成代碼
class User_ constructor(_nickName: String) { val nickName: String init { println("init 1") nickName = _nickName } init { println("init 2") }
* 上面的例子中出現了兩個關鍵字:constructor 、 init
* constructor用來開始一個主構造方法的聲明。init關鍵字用來引入一個初始化語句,“初始化語句塊”包含了再類被創建的時候所執行的代碼,並會與主構造方法一起使用。
* 因為主構造方法受語法限制,不能包含初始化代碼,這就是為什么要使用初始化語句的原因。而且,可以再一個類中聲明多個初始化語句塊
* 在上面的例子中不需要把初始化代碼放到初始化語句塊中,因為它可以與nickName屬性的聲明結合。
* 如果主構造方法沒有注解或者可見性修飾符,同樣可以去掉constructor修飾符,如下面的聲明
class User0(_nickName: String) { val nickName = _nickName }
* 在上面的兩個列子中,使用val 聲明了屬性。
* 如果屬性用相應的構造方法參數來初始化代碼可以通過把val關鍵字加在參數前的方式來進行簡化,這樣就能替換掉類中的屬性定義,如下
class User1(val name: String) //val 意味着響應的屬性會用構造方法的參數來初始化
* 可以像普通函數一樣,為構造方法參數聲明一個默認值
* 如果所有的構造方法參數都有默認值,編譯器會生成一個額外的不帶參數的構造方法來使用所有的默認值,這可以讓Kotlin使用庫的時候變得簡單,因為可以使用無參的構造方法來實例化。
class User2(val name: String, val isSubscribed: Boolean = false)
接下來展示帶有繼承的構造方法,首先給出個父類
open class Student(val name: String)
* 如果你的類具有一個父類,主構造方法同樣要初始化父類,可以通過在基類列表的父類引用中提供 父類構造方法參數 的方式來做到這一點
class TwitterStudent(nick: String) : Student(nick)
* 如果沒有給一個類聲明任何構造方法,將會生成一個不帶參數的不做任何事的默認構造函數
open class Animal
* 自動生成的默認的無參的構造函數就是為什么在繼承一個類的時候加括號的原因,注意與接口實現的區別
* 接口沒有構造方法,所以在你實現一個接口的時候不需要在父類型列表中它的名稱后面再加上括號
class Bird : Animal() {}
* 如果想讓要確保一個類不被其他代碼實例化,就必須把構造方法標為private的
* Kotlin中的單例工具類會少甚多,因為頂層函數可以作為靜態實用工具
class Secretice private constructor() {}
* Kotlin中不主張聲明多個重載的構造函數,取而代之的應該是直接標記默認參數。
* 但是,Kotlin 也是支持多個構造方法的,如下
* View1沒有主構造方法,但是它聲明了兩個從構造方法,從 構造方法也用constructor 引出,也一樣可以聲明多個從構造方法
open class View1 { constructor(ctx: String) { //.. } constructor(ctx: String, attr: Int) { //.. } }
* 如果要擴展上面的View1,同樣可以聲明多個從構造方法
class EditText : View1 { /** * 在構造方法后面使用 :this 來調用本類的構造方法 */ constructor(ctx: String) : this(ctx, 1) { } /** * 在構造方法后面使用 :super 來調用父構造方法 */ constructor(ctx: String, attr: Int) : super(ctx, attr) { } constructor(ctx: String, attr: Int, args: Array<String>) : super(ctx) { } }
* 如果有主構造方法,就可以直接在聲明子類的時候初始化父類的方法,
* 像EditText,如果沒有主構造方法,那么每個從構造方法必須初始化基類,或者委托給另一個這樣做了的從構造方法。
* 每個構造方法必須以一個朝外的箭頭開始並且結結束於任意一個基類構造方法
class TextView(ctx: String) : View1(ctx) {}