Kotlin的構造函數(shù)

Kotlin的構造函數(shù)分為主構造器(primary constructor)和次級構造器(secondary constructor)。

一、 Primary Constructor

  1. 寫法一:
    class 類名 constructor(形參1, 形參2, 形參3){}
class Person constructor(username: String, age: Int){
    private val username: String
    private var age: Int
 
    init{
        this.username = username
        this.age = age
    }
}

這里有兩個關鍵點:
1、關鍵字constructor:在Java中,構造方法名須和類名相同;而在Kotlin中,是通過constructor關鍵字來標明的,且對于Primary Constructor而言,它的位置是在類的首部(class header)而不是在類體中(class body)。

2、關鍵字init:init{}它被稱作是初始化代碼塊(Initializer Block),它的作用是為了Primary Constructor服務的,由于Primary Constructor是放置在類的首部,是不能包含任何初始化執(zhí)行語句的,這是語法規(guī)定的,那么這個時候就有了init的用武之地,我們可以把初始化執(zhí)行語句放置在此處,為屬性進行賦值。

  1. 寫法二(演變一):
    a. 當constructor關鍵字沒有注解和可見性修飾符作用于它時,constructor關鍵字可以省略(當然,如果有這些修飾時,是不能夠省略的,并且constructor關鍵字位于修飾符后面)。那么上面的代碼就變成:
class Person (username: String, age: Int){
    private val username: String
    private var age: Int
 
    init{
    this.username = username
    this.age = age
    }
}

b. 初始化執(zhí)行語句不是必須放置在init塊中,我們可以在定義屬性時直接將主構造器中的形參賦值給它。

class Person(username: String, age: Int){
    private val username: String = username
    private var age: Int = age
}

其實寫法二實際上就是對寫法一前面提到的兩個關鍵字的簡化。

  1. 寫法三(演變二):
    這種在構造器中聲明形參,然后在屬性定義進行賦值,這個過程實際上很繁瑣,我們是可以直接在Primary Constructor中定義類屬性的。
class Person(private val username: String, private var age: Int){}

如果類不包含其他操作函數(shù),那么連花括號也可以省略

class Person(private val username: String, private var age: Int)
  1. 當我們定義一個類時,我們如果沒有為其顯式提供Primary Constructor,Kotlin編譯器會默認為其生成一個無參主構造,這點和Java是一樣的。比如有這樣的一個類:

二、 Secondary Constructor
1.示例:

class User{
    private val username: String
    private var age: Int
        
    constructor(username: String, age: Int){
        this.username = username
        this.age = age
    }
}

和Primary Constructor相比,很明顯的一點,Secondary Constructor是定義在類體中。第二,Secondary Constructor可以有多個,而Primary Constructor只會有一個。

  1. 要想實現(xiàn)屬性的初始化,實際上主構造器已經能夠應付多數(shù)情況了,為什么還需要次級構造器?主要原因是因為我們有時候是需要去繼承框架中的類。如在Android中你自定義一個ViewPager:
/**
 * 不可以滑動,但是可以setCurrentItem的ViewPager。
 */
class NoScrollViewPager : ViewPager {
    private var canScroll: Boolean = false

    fun setCanScroll(scroll: Boolean) {
        this.canScroll = scroll
    }

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    override fun onTouchEvent(arg0: MotionEvent): Boolean {
        return if (canScroll) {
            super.onTouchEvent(arg0)
        } else {
            false
        }
    }
    override fun onInterceptTouchEvent(arg0: MotionEvent): Boolean {
        return false
    }
    //去除頁面切換時的滑動翻頁效果
    override fun setCurrentItem(item: Int, smoothScroll: Boolean) {
        super.setCurrentItem(item, smoothScroll)
    }
    override fun setCurrentItem(item: Int) {
        super.setCurrentItem(item, false)
    }
}

在這種情況下,你如果需要重寫ViewPager 的多個構造器,那么,就需要用到Secondary Constructor。同樣,這里也有幾點需要注意:

1、可以看到,我們可以使用this關鍵字來調用自己的其他構造器,并且需要注意它的語法形式,次級構造器: this(參數(shù)列表)

2、可以使用super關鍵字來調用父類構造器,當然這塊內容我們放到繼承那塊再來介紹。這里是為了說明Secondary Constructor的作用,實際上在開發(fā)中我們可以使用默認參數(shù)來使代碼簡化!

  1. 我們再來看這樣一種情況,我們同時定義了主構造器和次級構造器:

class Student constructor(username: String, age: Int) {
 
 
    private val username: String = username
    private var age: Int = age
    private var address: String
    private var isMarried: Boolean
 
    init {
        this.address = "Beijing"
        this.isMarried = false
    }

    constructor(username: String, age: Int, address: String) :this(username, age) {
 
        this.address = address
    }
 
    constructor(username: String, age: Int, address: String, isMarried: Boolean) : this(username, age, address) {
        this.isMarried = isMarried
    }
}

這種情況四個參數(shù)的次級構造調用三個參數(shù)的次級構造,而三個參數(shù)的次級構造又調用了主構造。換句話,次級構造會直接或者間接調用主構造。這也就是這個例子需要說明的問題。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容