注意:屬性和變量不同,屬性是指一組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
}
}