類成員
類成員包括 成員方法 和 成員屬性:
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 直接初始化
最新評論