首頁>技術>

類成員

類成員包括 成員方法 和 成員屬性:

class Artist(var name: String) { // 成員屬性 name    var age = 18 // 成員屬性 age    fun dance(danceName: String) { // 成員方法 dance        println("$name 正在跳 $danceName")    }    fun sing(singName: String) { // 成員方法 sing        println("$name 正在唱 $singName")    }}

類中的 dance 和 sing 是成員方法,age 是成員屬性,使用 var 或 val 宣告的構造器引數 name 也會成為類成員屬性。

函式與方法

函式與方法形式一致,區別是方法在類中,函式則不是,因此,方法需要透過類名或物件來呼叫,而函式則是直接使用。

函式強調功能本身,不考慮從屬。

// 函式fun sayHello() {    println("hello")}fun main(args: Array<String>) {    val artist = Artist("lqr")    artist.dance("恰恰") // 呼叫物件 artist 的 dance 方法    artist.sing("龍捲風") // 呼叫物件 artist 的 sing 方法    sayHello() // 呼叫函式}

屬性訪問控制

先來看個訪問物件屬性的例子:

class AClass {    var b = 0}fun main() {    val a = AClass()    a.b = 666    println(a.b) // 666}

Kotlin 中,物件訪問屬性實質上都是使用 getter/setter ,而並非直接訪問屬性對其賦值。這可以透過重寫屬性的 getter/setter 來驗證:

class AClass {    var b = 0        get() {            println("some one tries to get b.")            return field        }        set(value) {            println("some one tries to set b.")            field = value        }}fun main() {    val a = AClass()    a.b = 666 // some one tries to set b.    println(a.b) // some one tries to get b.                 // 666}

getter/setter 中使用屬性時,需要用 field 來指代,避免出現程式碼歧義。

注意:val 常量沒有 setter,因為 val 是不可變的!

預設屬性的 getter/setter 的訪問許可權是 public,可以對其重寫修改:

class AClass {    var b = 0        protected get // IDE報錯:Getter visibility must be the same as property visibility        protected set}

如果修改了 getter 的訪問許可權,就需要對屬性宣告做同樣的修改,於是,正確的寫法是:

class AClass {    protected var b = 0        protected get        protected set}

屬性初始化

Kotlin 中一般成員屬性在宣告時就需要初始化:

class AClass {    var b = 0    var c: String? = null    // var c: String? // IDE報錯:Property must be initialized or be abstract}

Kotlin 也支援屬性延遲初始化,但 var 和 val 的延遲初始化寫法完全不同,var 變數使用 lateinit:

class Xclass AClass {    lateinit var c: String    lateinit var d: X    // lateinit val e:X // IDE報錯:'lateinit' modifier is allowed only on mutable properties}fun main(args: Array<String>) {    val a = AClass()    a.d = X()    println(a.d) // com.charylin.kotlinlearn.X@214c265e    println(a.c) // lateinit property c has not been initialized}
lateinit 只能與 var 搭配,不能與 val 一起使用。lateinit var 變數在使用前一定要確保已經初始化,否則報錯:lateinit property c has not been initialized。

說完 lateinit var ,再來看看 val 常量的延遲初始化,使用的是 by lazy,作用是 "使用時載入":

class Xclass AClass {    // val e: X by lazy {} // IDE報錯:Type mismatch. Required:X Found: Unit    val e: X by lazy {        println("init X")        X()    }}fun main(args: Array<String>) {    val a = AClass()    println("init a") // init a    println(a.e) // init X                 // com.charylin.kotlinlearn.X@3d075dc0}

關於屬性初始化的幾點建議:

屬性的初始化儘量在構造方法中完成無法在構造方法中初始化,嘗試降級為區域性變數var 用 lateinit 延遲初始化,val 用 lazy可空型別慎用 null 直接初始化

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 27歲發明SQL以後,上帝把他帶走了