注意:属性和变量不同,属性是指一组get和set方法和backing field,变量是指field
var是可变属性,val是赋值一次,可读属性
public class Address {
public var name: String = ...
public var street: String = ...
public var city: String = ...
public var state: String? = ...
public var zip: String = ...
}
//使用属性
fun copyAddress(address: Address): Address {
val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}
定义var属性的语法:
var <propertyName>: <PropertyType> [= <property_initializer>]
[<getter>]
[<setter>]
initializer
,getter
,setter
都是可选的,属性类型如果从initializer
或者父类变量中可以推断出来,则可以省略,getter
,setter
没写则会自动生成
val必须在定义或者constructor
中赋值
重写getter
val isEmpty: Boolean
get() = this.size == 0
重写setter
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
如果只想改变修饰符,而不重新定义getter和setter,可以不用写body
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
Fields
Kotlin中的类没有field,但是有时写自定义访问函数时,需要使用backing field,使用field
来访问backing field,field
只能在访问方法只使用
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
除了backing field,还可以使用backing property
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
}
return _table ?: throw AssertionError("Set to null by another thread")
}
编译时常量
编译能获取值的属性可以用const来修饰
- Top-level或者object的属性
- 类型为String或者其他primitive type
- 没有自定义getter
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
延迟初始化的属性
任何type为非null的属性都要在构造函数或者定义时初始化,否则需要使用lateinit
来修饰
- 只能是
var
属性 - 在body里定义,不在primary constructor里定义
- non-null type, not primitive type
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}