在之前的文章中我們講到,Kotlin類中的屬性既可以用關(guān)鍵字var
聲明為可變的帖烘,也可以用關(guān)鍵字val
聲明為只讀的亮曹。
成員變量(屬性)
默認(rèn)情況下,使用var/val聲明的屬性可通過對(duì)象直接訪問秘症,即是public修飾的,除非為屬性聲明private修飾符式矫。
open class Person {
var age: Int? = null
}
@JvmStatic
fun main(args: Array<String>) {
val p = Person()
//為屬性賦值
p.age = 10
println(p.age.toString())
}
在Kotlin的世界里成員變量也可被子類復(fù)寫乡摹。同方法的復(fù)寫一樣,需要在父類的成員屬性前聲明open表示可復(fù)寫采转,子類聲明override表示重寫聪廉。
open class Person {
//屬性聲明open表示可重寫
open var age: Int? = null
}
open class Student: Person() {
//重寫父類屬性
override var age: Int? = 10*10
}
默認(rèn)情況下屬性在聲明時(shí)必須賦值,除非把屬性也聲明為abstract的故慈,類中有抽象屬性時(shí)必須聲明為抽象類板熊。
非基本類型的不可空類型(val)的屬性可延遲初始化賦值,使用lateinit
實(shí)現(xiàn)該功能察绷。只要保證在使用此屬性時(shí)已賦值即可干签,若仍未賦值則會(huì)拋出屬性尚未初始化異常。
open class Person {
//延遲初始化
lateinit var str: String
fun getUpper(): String {
return str.toUpperCase()
}
}
@JvmStatic
fun main(args: Array<String>) {
val p = Person()
//kotlin.UninitializedPropertyAccessException
//lateinit property str has not been initialized
println(p.getUpper())
}
若想避免上述異巢鸷常可以在使用屬性前使用isInitialized方法判斷容劳。
open class Person {
lateinit var str: String
fun work() {
if(::str.isInitialized) {
println("str is isInitialized")
} else {
println("str is not isInitialized")
}
}
}
getter/setter
默認(rèn)情況下每個(gè)屬性都具有g(shù)etter/setter方法
聲明一個(gè)屬性的完整語(yǔ)法如下:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
屬性初始值喘沿、getter/setter是可缺省,如果屬性類型可以從初始值或getter中推斷出來(lái)則也可缺省竭贩。val類型的屬性不具備setter蚜印。
屬性的getter/setter均可復(fù)寫,即自定義訪問器留量。如果我們定義了一個(gè)自定義的setter窄赋,那么每次給屬性賦值時(shí)都會(huì)調(diào)用它。
來(lái)看一個(gè)例子:
open class Person {
var age: Int = 10
//getter缺省為默認(rèn)
//setter設(shè)置參數(shù)前打印參數(shù)
set(value) {
println("setter $value")
//field關(guān)鍵字指向?qū)傩员旧? field = value
}
}
@JvmStatic
fun main(args: Array<String>) {
val p = Person()
println(p.age)
p.age = 30
println(p.age)
}
打印結(jié)果:
10
setter 30
30
這里需要解釋一下楼熄,set方法聲明的value是參數(shù)名忆绰,表示屬性實(shí)際賦值時(shí)的那個(gè)對(duì)象,約定俗成寫做value孝赫,可以隨意寫成其他较木。
field
指向當(dāng)前屬性,field標(biāo)識(shí)符只能用在屬性的訪問器內(nèi)青柄。
若想控制setter訪問伐债,可以私有化setter。
var setterVisibility: String = "abc"
// 此 setter 是私有的并且有默認(rèn)實(shí)現(xiàn)
private set