Kotlin學習筆記(四)屬性

提示:本文爲作者閱讀Kotlin中文站學習筆記,建議讀者移步Kotlin中文站完整學習。

屬性

Kotlin的類可以有屬性。我們可以使用var關鍵字聲明一個可變的屬性,或val關鍵字聲明一個只讀的屬性。

class R{
    var a:String=""//var 聲明一個可變的屬性
    val b:String=""//val 聲明一個只讀的屬性
}

聲明一個屬性的完整語法是:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]

初始化其(initializer),getter/setter方法都是可選的,屬性類型如果可以從初始化器或getter方法中判斷出,也可以省略。

var c:String
    get() = ""
    set(value) {
        c=value
    }
val d=1//Int 默認getter實現,類型可以從初始化器中判斷出來,可以省略

一個只讀屬性的語法和一個可變的屬性的語法有兩方面的不同:1、只讀屬性的用 val開始代替var 2、只讀屬性不允許 setter。

如果你需要改變一個訪問器的可見性或者對其註解,但是不需要改變默認的實現, 你可以定義訪問器而不定義其實現:

private var a:String=""//var 聲明一個可變的屬性
private get//改變訪問器的可變性,不改變其默認實現

幕後字段

Kotlin 中類不能有字段。然而,當使用自定義訪問器時,有時有一個幕後字段(backing field)有時是必要的。爲此 Kotlin 提供一個自動幕後字段,它可通過使用 field 標識符訪問。

var c:String=""// 此初始器值直接寫入到幕後字段
    set(value) {
        field=value
    }

field 標識符只能用在屬性的訪問器內。
如果屬性至少一個訪問器使用默認實現,或者自定義訪問器通過 field 引用幕後字段,將會爲該屬性生成一個幕後字段。下面的情況屬性就沒有幕後字段:

//c屬性沒有幕後字段,無法初始化
var c:String
    get() = ""
    set(value) {
        c=value
    }
//c屬性有幕後字段,必須初始化
var c:String=""
    get() = ""
    set(value) {
        field=value//自定義訪問器通過field訪問幕後字段
    }

幕後屬性

如果你的需求不符合這套“隱式的幕後字段”方案,那麼總可以使用 幕後屬性(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")
    }

從各方面看,這正是與 Java 相同的方式。因爲通過默認 getter 和 setter 訪問私有屬性會被優化,所以不會引入函數調用開銷。

編譯期常量

已知值的屬性可以使用 const 修飾符標記爲 編譯期常量。 這些屬性需要滿足以下要求:

  • 位於頂層或者是 object 的一個成員
  • 用 String 或原生類型 值初始化
  • 沒有自定義 getter

這些屬性可以用在註解中:

const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"

@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { …… }

延遲初始化屬性

一般地,屬性聲明爲非空類型必須在構造函數中初始化。 然而,這經常不方便。例如:屬性可以通過依賴注入來初始化, 或者在單元測試的 setup 方法中初始化。 這種情況下,你不能在構造函數內提供一個非空初始器。 但你仍然想在類體中引用該屬性時避免空檢查。

爲處理這種情況,你可以用 lateinit 修飾符標記該屬性:

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // 直接解引用
    }
}

該修飾符只能用於在類體中(不是在主構造函數中)聲明的 var 屬性,並且僅當該屬性沒有自定義 getter 或 setter 時。該屬性必須是非空類型,並且不能是原生類型。

在初始化前訪問一個 lateinit 屬性會拋出一個特定異常,該異常明確標識該屬性被訪問及它沒有初始化的事實。

發佈了59 篇原創文章 · 獲贊 13 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章