一、属性声明
Kotlin 中的属性使用var
声明为可变属性,val
声明位只读属性
1
2
3
4
5
6
7
class Address {
var name: String = "Holmes, Sherlock"
val street: String = "Baker"
var city: String = "London"
var state: String? = null
val zip: String = "123456"
}
属性的完整语法格式如下,初始化、getter、setter都是可选的,如果类型可以推导出来的话,类型也可以省略
1
2
3
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
可以自定义getter、setter的访问器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value)
}
class Rectangle(val width: Int, val height: Int) {
val area: Int
get() = this.width * this.height
//当类型可以推导时,也可以简写成这样
val area get() = this.width * this.height
}
如果需要修改访问器的可见性或添加注解时可以像下面这样
1
2
3
4
5
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
var setterWithAnnotation: Any? = null
@Inject set // annotate the setter with Inject
在访问器中使用当前属性时应该获取当前作用域下的field
字段,被称为“ backing fields”
1
2
3
4
5
6
var counter = 0 // 这个初始器直接为幕后字段赋值
set(value) {
if (value >= 0)
field = value
// counter = value // ERROR StackOverflow: Using actual name 'counter' would make setter recursive
}
二、编译期常量
如果属性在编译期已经是已知的,那应该使用const
关键字进行标记。添加const
需要满足以下几个条件
- 必须是顶级属性 或 声明为
object
或是伴生对象 - 必须以String 或 原生类型进行初始化
- 不可以自定义getter
三、属性的延迟初始化
通常来说声明为非空类型则必须在构造函数中进行初始化,这样可能会带来一些不便,例如可能通过依赖注入的方式进行初始化,这种情况下可以使用lateinit
进行标记,告知我们要延迟初始化
1
2
3
4
5
6
7
8
9
10
11
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}
需要 lateinit 不可以用在原生类型上,如:Int,Float等
如需要检查lateinit
是否进行了初始化,可以调用.isInitialized
方法,注意::
符号
1
2
3
if (foo::bar.isInitialized) {
println(foo.bar)
}