kotlin類和對象—>屬性與字段
1.聲明屬性,Kotlin 類中的屬性既可以用關鍵字 var 聲明為可變的,也可以用關鍵字 val 聲明為只讀的
class Address { var name: String = "Holmes, Sherlock" var street: String = "Baker" var city: String = "London" var state: String? = null var zip: String = "123456" } //要使用一個屬性,只要用名稱引用它即可 fun copyAddress(address: Address): Address { val result = Address() // Kotlin 中沒有“new”關鍵字 result.name = address.name // 將調用訪問器 result.street = address.street // ...... return result }
2.Getters與Setters
2.1 聲明一個屬性的完整語法是
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>] [<setter>]
2.2 其初始器( initializer )、getter 和 setter 都是可選的屬性類型如果可以從初始器 ( 或者從其getter返回值,如下文所示)中推斷出來,也可以省略
例如
var allByDefault: Int? // 錯誤:需要顯式初始化器,隱含默認 getter 和 setter var initialized = 1 // 類型 Int、默認 getter 和 setter
2.3 只讀屬性不允許setter
val simple: Int? // 類型 Int、默認 getter、必須在構造函數中初始化 val inferredType = 1 // 類型 Int 、默認 getter
2.4 我們可以為屬性定義自定義的訪問器。如果我們定義了一個自定義的 getter,那么每次訪問該屬性時都 會調用它(這讓我們可以實現計算出的屬性)。以下是一個自定義 getter 的示例
val isEmpty: Boolean get() = this.size == 0
2.5 如果我們定義了一個自定義的 setter,那么每次給屬性賦值時都會調用它。一個自定義的 setter 如下所
var stringRepresentation: String get() = this.toString() set(value) { setDataFromString(value) // 解析字符串并賦值給其他屬性 }
2.6 自kotlin1.1起,如果可以從getter推斷出屬性類型,則可以省略它
val isEmpty get() = this.size == 0 // 具有類型 Boolean
2.7 如果你需要改變一個訪問器的可?性或者對其注解,但是不需要改變默認的實現,你可以定義訪問器而不定義其實現
//主要用于,內部實現改變的方式,但是不允許外部去改變 var setterVisibility: String = "abc" private set // 此 setter 是私有的并且有默認實現 var setterWithAnnotation: Any? = null @Inject set // 用 Inject 注解此 setter
3.幕后字段:在 Kotlin 類中不能直接聲明字段。然而,當一個屬性需要一個幕后字段時,Kotlin 會自動提供。這個幕后 字段可以使用 field 標識符在訪問器中引用
var counter = 0 // 注意:這個初始器直接為幕后字段賦值 set(value) { if (value >= 0) field = value } //field 標識符只能用在屬性的訪問器內,例如滿足某種條件才會去賦值
4.幕后屬性,如果你的需求不符合這套“隱式的幕后字段”方案,那么總可以使用 幕后屬性(backing property)
private var _table: Map<String, Int>? = null public val table: Map<String, Int> get() { if (_table == null) { _table = HashMap() // 類型參數已推斷出 } return _table ?: throw AssertionError("Set to null by another thread") } //對于 JVM 平臺:通過默認 getter 和 setter 訪問私有屬性會被優化,所以本例不會引入函數調用開 銷
5.編譯期常量,如果只讀屬性的值在編譯期是已知的,那么可以使用 const 修飾符將其標記為編譯期常量
//這種屬性需要滿足以下要求: //— 位于頂層或者是object聲明或companion object的一個成員 //— 以 String 或原生類型值初始化 //— 沒有自定義getter // 這些屬性可以用在注解中: const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated" @Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ...... }
6.延遲初始化屬性和變量,一般地,屬性聲明為非空類型必須在構造函數中初始化。然而,這經常不方便。例如:屬性可以通過依賴 注入來初始化,或者在單元測試的 setup 方法中初始化。這種情況下,你不能在構造函數內提供一個非 空初始器。但你仍然想在類體中引用該屬性時避免空檢測。
為處理這種情況,你可以用 lateinit 修飾符標記該屬性
public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() // 直接解引用 } }
6.1 檢查一個lateinit var 是否已被初始化(自kotlin 1.2起)
if (foo::bar.isInitialized) { println(foo.bar) }

浙公網安備 33010602011771號