属性必须初始化, 如果没有直接赋值, 就必须写进构造函数中
声明在主构造函数中的属性:
class PfA(val a: Int, var b: Int)
声明属性, 然后在次构造函数中初始化或 init
块中初始化.
class PfB {
var a: Int
val b: Int
val c: Int?
// 次构造函数中不能有 val, var
constructor(a: Int, b: Int, c: Int) {
this.a = a
this.b = b
this.c = c
}
}
class PfBB(a: Int, b: Int) {
val a = a
val b: Int
init {
this.b = b
}
}
直接赋值初始化的属性:
class PfC {
var a = 0
val b = 1
// val 类型属性可以这样初始化, 但是 var 不行!
// 这样是没有 backing field 的
val c get() = true
}
完整的属性声明语法:
var <propertyName>[: <PropertyType>] [= <property_initializer]
[<getter>]
[<setter>]
初始化表达式, getter, setter 是可选的.
如果属性类型可以被初始化表达式推断, 或从 getter 的 return 返回值推断.
// val 只有 getter, 不能有 setter
// 可以从 getter 返回值推断类型, 所以类型可以不写
val allByDefault
get() = 1 // val 可以用 getter, 可以省略初始化表达式和类型
Backing Fields
Kotlin 中默认实现了 java 中的 getter, setter. 但也可以自定义, 修改逻辑.
注意: 如果不在构造函数中初始化, var 变量必须使用初始化表达式, 而 val 变量可以用
getter 代替初始化表达式
// Backing Fields
// 使用 field 标识符, 在 getter setter 内可以使用, 用来设置属性值.
var getsetvar: Int = 1
set(value) {
field = value + 1
}
// 使用 getter 可以用来做一些逻辑判断
var getsetvar2: Int = 1 // 这里是初始化
get() {
if(field == 1) {
println("值是 1, 返回 0")
return 0
}
return field
}
set(value) {
field = value + 1
}
测试验证上面的属性:
@Test fun testProperties() {
// 初始值是 1
assertEquals(1, address.getsetvar)
// 设置为 2
address.getsetvar = 2
// setter 会加 1, 所以值应该是 3
assertEquals(3, address.getsetvar)
}
@Test fun testProperties2() {
// 初始值是 1, getter 判断如果等于 1 就返回 0
assertEquals(0, address.getsetvar2)
// 设置为 3, setter 会加 1, 所以是 4
address.getsetvar2 = 3
assertEquals(4, address.getsetvar2)
}
访问器 getter setter 的可见性
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
Compile-Time Constants
编译时常量:
- Top-level or member of an object
- Initialized with a value of type String or a primitive type
- No custom getter
这类属性可以用在注解中:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
延迟初始化属性(Late-Initialized Property)
用于依赖注入或测试方法中在 @setup, @before
等方法中再进行初始化.
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}