文章目录
- 定义
- field 字段(Backing Fields)
定义
我们可以为变量定义get
(无参数,有与变量同类型的放返回值)或set
(有一个与变量类型相同的参数,返回Unit
)函数,在取值(get
)和赋值(set
)时进行一些其他操作,get
函数称为 getter,set
函数称为 setter。
var 变量名[: 变量类型] = 初始值gettersetter// val 没有 setter
val 变量名[: 变量类型]getter
getter 和 setter 在定义时就像在写函数一样,但你不需要写fun
关键字或声明返回值类型。
getter 和 setter 会给变量附上类似函数的特性,在很多时候会派上大用场:
// 不用 getter
var width = 10var height = 10val area = width * heightfun main() {println(area)// 改变值width = 20height = 20print(area)
}
100
100
// 使用 getter
var width = 10var height = 10val area get() = width * heightfun main() {println(area)// 改变值width = 20height = 20print(area)
}
100
400
field 字段(Backing Fields)
有一个很有趣的问题,如果我们要在 getter 或 setter 中访问变量的值或者赋值,该怎么办?如果你尝试使用变量名进行访问(或赋值),IDEA 会提示"递归属性访问器"。如果你看到这只是个警告,不以为然的将其运行,会受到一串长长的红字,在开头则给出了java.lang.StackOverflowError
,栈溢出:
val name: Stringget() {println(name)return "Kotlin"}fun main() {name
}
这是因为你在get
中访问name
,会再一次调用get
,而新的一次调用中又访问了name
······so,什么时候才是个头?为此,Kotlin 提供了field
关键字,你可以像使用this
一样很自然地使用field
,无需声明,使用它获取值或赋值不会造成递归问题:
var name: String = "K1"get() {println("getter")return field}set(value: String) {println("setter")field = value}fun main() {// 当定义了 getter 和 setter// 每次对变量操作时,都会调用对应方法println(name)name = "K2"print(name)
}
getter // 访问值, get 被调用,先打印了 getter
K1 // 返回的 K1 被打印
setter // 赋值,set 被调用
getter // get 再次被调用,打印 getter
K2 // 返回新的值 K2