先看下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