【第6篇】Kotlin的屬性與字段詳解

1、聲明屬性

  • Kotlin 類中的屬性既可以用關鍵字 var聲明為可變的忿项,也可以用關鍵字 val聲明為只讀的。
class Address {
    var name: String = ""http://地址名稱
    var street: String = ""http://街道
    var city: String =""http://城市名稱
    var state: String? ="" //狀態(tài)可以為空null
    var zip: String =""http://郵政編碼
}
  • 要使用一個屬性,只要用名稱引用它即可算撮,就像 Java 中的字段:
fun copyAddress(address: Address): Address {
    val result = Address() // Kotlin 中沒有“new”關鍵字
    result.name = address.name // 將調用訪問器
    result.street = address.street
    // ……
    return result
}
  • 2、 Getters 與 Setters

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

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
  • 其初始器(initializer)县昂、getter 和 setter 都是可選的肮柜。屬性類型如果可以從初始器 (或者從其 getter 返回值,如下文所示)中推斷出來倒彰,也可以省略审洞。
var allByDefault: Int? // 錯誤:需要顯式初始化器,隱含默認 getter 和 setter
var initialized = 1 // 類型 Int待讳、默認 getter 和 setter
  • 一個只讀屬性的語法和一個可變的屬性的語法有兩方面的不同:1芒澜、只讀屬性的用 val開始代替var 2、只讀屬性不允許 setter
val simple: Int? // 類型 Int创淡、默認 getter痴晦、必須在構造函數中初始化
val inferredType = 1 // 類型 Int 、默認 getter
  • 我們可以為屬性定義自定義的訪問器琳彩。如果我們定義了一個自定義的 getter誊酌,那么每次訪問該屬性時都會調用它 (這讓我們可以實現(xiàn)計算出的屬性)。以下是一個自定義 getter 的示例:
val isEmpty: Boolean
    get() = this.size == 0
  • 如果我們定義了一個自定義的 setter露乏,那么每次給屬性賦值時都會調用它碧浊。一個自定義的 setter 如下所示
var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value) // 解析字符串并賦值給其他屬性
    }
  • 按照慣例,setter 參數的名稱是 value施无,但是如果你喜歡你可以選擇一個不同的名稱辉词。自 Kotlin 1.1 起,如果可以從 getter 推斷出屬性類型猾骡,則可以省略它
val isEmpty get() = this.size == 0  // 具有類型 Boolean
  • 如果你需要改變一個訪問器的可見性或者對其注解瑞躺,但是不需要改變默認的實現(xiàn), 你可以定義訪問器而不定義其實現(xiàn):
var setterVisibility: String = "abc"
    private set // 此 setter 是私有的并且有默認實現(xiàn)

var setterWithAnnotation: Any? = null
    @Inject set // 用 Inject 注解此 setter

3兴想、幕后字段

  • 在 Kotlin 類中不能直接聲明字段幢哨。然而,當一個屬性需要一個幕后字段時嫂便,Kotlin 會自動提供捞镰。這個幕后字段可以使用field標識符在訪問器中引用:
var counter = 0 // 注意:這個初始器直接為幕后字段賦值
    set(value) {
        if (value >= 0) field = value
    }
  • field 標識符只能用在屬性的訪問器內,如果屬性至少一個訪問器使用默認實現(xiàn),或者自定義訪問器通過 field 引用幕后字段,將會為該屬性生成一個幕后字段岸售。例如践樱,下面的情況下, 就沒有幕后字段
val isEmpty: Boolean
    get() = this.size == 0

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")
    }
  • 從各方面看,這正是與 Java 相同的方式屎慢。因為通過默認 getter 和 setter 訪問私有屬性會被優(yōu)化瞭稼,所以不會引入函數調用開銷。

5腻惠、編譯期常量

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

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()  // 直接解引用
    }
}

1、該修飾符只能用于在類體中的屬性(不是在主構造函數中聲明的 var 屬性牙咏,并且僅當該屬性沒有自定義 getter 或 setter 時)臼隔,而自 Kotlin 1.2 起,也用于頂層屬性與局部變量妄壶。該屬性或變量必須為非空類型摔握,并且不能是原生類型。
2丁寄、在初始化前訪問一個 lateinit 屬性會拋出一個特定異常氨淌,該異常明確標識該屬性被訪問及它沒有初始化的事實。
3伊磺、檢測一個 lateinit var 是否已初始化(自 1.2 起)

  • 要檢測一個 lateinit var 是否已經初始化過盛正,請在該屬性的引用上使用 .isInitialized
if (foo::bar.isInitialized) {
    println(foo.bar)
}
  • 此檢測僅對可詞法級訪問的屬性可用,即聲明位于同一個類型內屑埋、位于其中一個外圍類型中或者位于相同文件的頂層的屬性豪筝。

7、覆蓋屬性

參見覆蓋屬性

8、委托屬性

  • 最常見的一類屬性就是簡單地從幕后字段中讀刃隆(以及可能的寫入)敲街。 另一方面,使用自定義 getter 和 setter 可以實現(xiàn)屬性的任何行為严望。 介于兩者之間多艇,屬性如何工作有一些常見的模式。一些例子:惰性值著蟹、 通過鍵值從映射讀取墩蔓、訪問數據庫、訪問時通知偵聽器等等萧豆。

  • 這些常見行為可以通過使用委托屬性實現(xiàn)為庫奸披。


文章來自koltin英文社區(qū)
文章來自koltin中文社區(qū)

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涮雷,隨后出現(xiàn)的幾起案子阵面,更是在濱河造成了極大的恐慌,老刑警劉巖洪鸭,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件样刷,死亡現(xiàn)場離奇詭異,居然都是意外死亡览爵,警方通過查閱死者的電腦和手機置鼻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜓竹,“玉大人箕母,你說我怎么就攤上這事【慵茫” “怎么了嘶是?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛛碌。 經常有香客問我聂喇,道長,這世上最難降的妖魔是什么蔚携? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任希太,我火速辦了婚禮,結果婚禮上酝蜒,老公的妹妹穿的比我還像新娘跛十。我一直安慰自己,他們只是感情好秕硝,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布芥映。 她就那樣靜靜地躺著洲尊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奈偏。 梳的紋絲不亂的頭發(fā)上坞嘀,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音惊来,去河邊找鬼丽涩。 笑死,一個胖子當著我的面吹牛裁蚁,可吹牛的內容都是我干的矢渊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼枉证,長吁一口氣:“原來是場噩夢啊……” “哼矮男!你這毒婦竟也來了?” 一聲冷哼從身側響起室谚,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤毡鉴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秒赤,有當地人在樹林里發(fā)現(xiàn)了一具尸體猪瞬,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年入篮,在試婚紗的時候發(fā)現(xiàn)自己被綠了陈瘦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡潮售,死狀恐怖甘晤,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情饲做,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布遏弱,位于F島的核電站盆均,受9級特大地震影響,放射性物質發(fā)生泄漏漱逸。R本人自食惡果不足惜泪姨,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饰抒。 院中可真熱鬧肮砾,春花似錦、人聲如沸袋坑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至婆誓,卻和暖如春吃环,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洋幻。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工郁轻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人文留。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓好唯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親燥翅。 傳聞我的和親對象是個殘疾皇子骑篙,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容