Kotlin之Set和Get
先看下kotlin裡的set和get的語法
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
格式就如上所示, set和get可寫也可不寫, 不寫的話會有預設的實現, 需要注意的是val修飾的變數是沒有set方法的, 也不允許重寫set方法, 例如下面這種寫法, 會提示不允許有set方法
看一個完整的例項程式碼
package com.wbing.kotlindemo class Student { var name : String = "zhang" // 這裡使用field而不是使用lastName, 是因為如果使用lastName會造成遞迴呼叫從而造成記憶體溢位, 因為使用lastName也會涉及到呼叫set/get的問題 get() = field.toUpperCase() var no : Int = 0 get() = field set(value) { if (value < 10) { field = value } else { field = -1 } } var classTeacher : String? = "孔子" set(value) = if (value == null) { field = "孔聖人" } else { field = value } /*set(value) = if (value == null) { this.classTeacher = "孔聖人" } else { this.classTeacher = value }*/ var isKZ : Boolean = true get() { return this.classTeacher == "孔聖人" } var className : String ? = "1班" // private set } fun main(args: Array<String>) { var stu: Student = Student() stu.name = "wang" println("lastName:${stu.name}") stu.no = 9 println("no:${stu.no}") stu.no = 20 println("no:${stu.no}") stu.classTeacher = null println(stu.classTeacher) println(stu.isKZ) stu.className = "一年一班" println(stu.className) }
以上的程式碼執行結果如下:
lastName:WANG
no:9
no:-1
孔聖人
true
一年一班
對於程式碼需要說明的有幾點:
1. field的用法, field被大神們翻譯成Backing Fields(後端變數), 它的作用就類似於java裡的this.屬性名, 例如上面程式碼中的第六行get() = field.toUpperCase(), 就相當於java裡的 this.name.toUpperCase(), 但是不能直接使用this.name會造成遞迴呼叫記憶體溢位的, 因為在set和get中是不允許有本身的區域性變數的(例如如果你屬性名是name, 在set/get裡是不能有這個變數的), 因為屬性的呼叫也涉及到了set/get會造成遞迴呼叫, 所以要解決引用自身的問題, kotlin發明了field(後端變數)來解決這個問題
注意不是set/get裡不允許有區域性變數, 是不允許有和屬性本身相同名字的區域性變數, 下面這種寫法是沒問題的
var test : Int = 0
get() {
var t = 1
field = t
return field
}
2. 注意程式碼中的第30~33行, 為什麼使用this.classTeacher不報錯, 是應為這個get方法是isKZ屬性的get, 而不是classTeacher的get方法
3. 如果把第36行的註釋開啟那麼main方法裡的stu.className="一年一班"會報如下錯誤
Error:(62, 5) Kotlin: Cannot assign to 'className': the setter is private in 'Student'
提示className屬性的setter是私有的不能被賦值, 通過這種方式我們可以禁止某些屬性被修改, 需要注意的是get方法不能隨便定義成private的, 需要和變數的可見範圍是一樣的, 如果變數是public的, 那麼get是不能設定成private的例如
var className : String ? = "1班"
private set
private get
這個會報錯: Error:(37, 9) Kotlin: Getter visibility must be the same as property visibility