Kotlin的属性和字段
Kotlin的属性相当于Java的字段再加上getter和setter方法。
一、读写属性和只读属性
Kotlin使用val定义只读属性,使用var定义读写属性,系统会为只读属性生成getter方法,会为读写属性生成getter和setter方法。
Kotlin定义普通属性时,需要显式指定初始值:要么在定义时指定初始值,要么在构造器中指定初始值。
class Address {
var street: String = ""
var city = ""
var province = ""
var postCode: String? = null
}
在定义属性时,如果系统可根据属性初识值推断出属性的类型,就可以不显式指定属性的类型。
Kotlin定义一个属性,就相当于定义一个Java类的private修饰的field,以及public、final修饰的getter和setter方法。
在Kotlin类中定义属性后,被Kotlin程序使用时只能使用点语法访问属性;被Java程序使用时只能通过getter、setter方法访问属性。
- 只读属性用val定义,读写属性用var定义;
- 只读属性不允许有setter方法。
二、自定义getter和setter
在定义属性时可指定自定义的getter和setter方法。
定义getter、setter方法时无须使用fun关键字。
fun main(args: Array<String>) {
var user = User("亮", "诸葛")
println(user.fullName)
}
class User(first: String, last: String) {
var first: String = first
var last: String = last
val fullName: String
//自定义getter方法
get() {
println("执行fullName的getter方法")
return "${first}.${last}"
}
}
输出结果:
执行fullName的getter方法
亮.诸葛
对于只读属性来说,只能重写getter方法;对于读写属性来说,可根据需要重写其中之一,也可同时重写它们。
fun main(args: Array<String>) {
var user = User("亮", "诸葛")
println(user.fullName)
user.fullName = "懿.司马"
println(user.first)
println(user.last)
}
class User(first: String, last: String) {
var first: String = first
var last: String = last
var fullName: String
//自定义getter方法
get() = "${first}.${last}"
set(value) {
println("执行fullName的setter方法")
if ("." !in value || value.indexOf(".") != value.lastIndexOf(".")) {
println("输入的fullName不合法")
} else {
var tokens = value.split(".")
first = tokens[0]
last = tokens[1]
}
}
}
输出结果:
亮.诸葛
执行fullName的setter方法
懿
司马
三、幕后字段
如果Kotlin类的属性有幕后字段,则Kotlin要求该属性显式指定初始值。
满足以下条件,系统就会为属性生成幕后字段:
- 该属性使用Kotlin自动生成的getter和setter方法或其中之一。
- 重写getter、setter方法时,使用field关键字显式引用了幕后字段。
fun main(args: Array<String>) {
var p = Person("悟空", 29)
p.age = 120
println(p.age)
p.age = 25
println(p.age)
}
class Person(name: String, age: Int) {
var name = name
set(newName) {
if (newName.length > 6 || newName.length < 2) {
println("您设置的人名不符合要求")
} else {
field = newName
}
}
var age = age
set(newAge) {
if (newAge > 100 || newAge < 0) {
println("您设置的年龄不合法")
} else {
field = newAge
}
}
}
输出结果:
您设置的年龄不合法
29
25
四、幕后属性
幕后属性就是用private修饰的属性,Kotlin不会为幕后属性生成任何getter、setter方法。
fun main(args: Array<String>) {
var p = Person("悟空", 29)
println(p.name)
p.name = "八戒"
println(p.name)
}
class Person(name: String, age: Int) {
private var _name = name
var name
get() = _name
set(newName) {
if (newName.length > 6 || newName.length < 2) {
println("您设置的人名不符合要求")
} else {
_name = newName
}
}
}
输出结果:
悟空
八戒
五、延迟初始化属性
Kotlin提供了lateinit修饰符来解决属性的延迟初始化。使用lateinit修饰的属性,可以在定义该属性时和在构造器中都不指定初始值。
lateinit修饰符有如下限制:
- lateinit只能修饰在类体中声明的可变属性。
- lateinit修饰的属性不能有自定义的getter或setter方法。
- lateinit修饰的属性必须是非空类型。
- lateinit修饰的属性不能是原生类型。
如果在lateinit属性赋初始值之前访问它,程序将会引发“lateinit property name has not been initialized”异常。
六、内联属性
inline修饰符可修饰没有幕后字段的属性的getter或setter方法,既可单独修饰属性的getter或setter方法;也可修饰属性本身,相当于同时修饰该属性的getter和setter方法。
fun main(args: Array<String>) {
var product = Product()
var name=product.author.name
println(name)
}
class Name(name: String, desc: String) {
var name = name
var desc = desc
}
class Product {
var productor: String? = null
//inline修饰属性的getter方法,表明读取属性时会内联化
val proName: Name
inline get() = Name("Python", "当前热推语言")
//inline修饰属性的setter方法,表明设置属性时会内联化
var author: Name
get() = Name("龟书", "一个大神")
inline set(v) {
this.productor = v.name
}
//inline修饰属性本身,表明读取和设置属性时都会内联化
inline var pubHouse: Name
get() = Name("开源社区", "无")
set(v) {
this.productor = v.name
}
}
输出结果:
龟书