Kotlin Backing Field

備用字段咽瓷?
幕后字段设凹?
支持字段?
后端域變量茅姜?
翻譯這么多種闪朱,其實(shí)都是一個(gè)意思 Backing Field

找到一些關(guān)于他的描述:

  • Kotlin中的類不能有field钻洒。但是奋姿,有時(shí)在使用自定義訪問器時(shí)必須有一個(gè) backing field 。為此素标,Kotlin提供了一個(gè)自動(dòng)backing field称诗,可以使用 field 標(biāo)識(shí)符來(lái)訪問。

  • Backing field is an autogenerated field for any property which can only be used inside the accessors(getter or setter) and will be present only if it uses the default implementation of at least one of the accessors, or if a custom accessor references it through the field identifier.This backing field is used to avoid the recursive call of an accessor which ultimately prevents the StackOverflowError.

  • 幕后字段是一個(gè)自動(dòng)生成的字段头遭,它僅僅可以被用在擁有至少一個(gè)默認(rèn)訪問器 (getter寓免、setter) 、或者在自定義訪問器中通過 field 標(biāo)識(shí)符修飾的屬性中计维。幕后字段可以避免訪問器的自遞歸而導(dǎo)致程序崩潰的 StackOverflowError 異常袜香。

那么這里有一些關(guān)于field的特點(diǎn):

  • field標(biāo)識(shí)符只允許在屬性的訪問器函數(shù)內(nèi)使用。
  • 如果你顯式地引用或者使用默認(rèn)的訪問器實(shí)現(xiàn)鲫惶,編譯器會(huì)為屬性生成field蜈首。
  • 如果你提供了一個(gè)自定義的訪問器實(shí)現(xiàn)并且沒有使用field,將不會(huì)生成field剑按。
  • 訪問屬性的方式不依賴于它是否含有field疾就。

在setter函數(shù)體中,使用了特殊標(biāo)記符field來(lái)訪問字段的值
在getter中艺蝴,只能讀取該值猬腰。
在setter中,既能讀取也能修改它猜敢。

//使用field關(guān)鍵字
public var fieldProp = ""
    get() = field
    set(value) {
        field = value
    }
//自定義不使用field 不生成:
val isEmpty: Boolean
    get() = this.size == 0
//默認(rèn)訪問器 生成:
val Foo.bar = 1

如果在類中定義一個(gè)成員變量姑荷,kotlin將自動(dòng)生成默認(rèn)的setter/getter方法盒延。
kotlin聲明get/set的方式為

  var name: String? = null
        set(value) {
            field = value
        }
        get() = field

這里使用了field,如果不使用field鼠冕,會(huì)這么寫:

  var name: String? = null
        set(value) {
            name = value
        }
        get() = name

但是這么寫添寺,對(duì)這個(gè)屬性進(jìn)行賦值并取值時(shí)出現(xiàn)了一些問題:


圖片1.png

在setter方法中對(duì)屬性進(jìn)行賦值和取值時(shí),會(huì)調(diào)用自身懈费,出現(xiàn)了遞歸調(diào)用计露。

這個(gè)時(shí)候field就可以解決這個(gè)問題了,backing field的作用域在當(dāng)前屬性的setter/getter方法中憎乙,以中間變量的形式票罐,來(lái)解決了遞歸問題。

在拓展屬性中

在拓展屬性中泞边,是沒有field這個(gè)字段的


圖片2.png

轉(zhuǎn)換一下寫法


圖片3.png

按照正常的寫法该押,這里報(bào)錯(cuò)。說明拓展屬性沒有field阵谚。
如果把這個(gè)拓展常量變成屬性蚕礼,會(huì)提示屬性必須初始化:


圖片4.png

那我們直接初始化試試


圖片5.png

直接賦值進(jìn)行初始化又報(bào)錯(cuò)了: 拓展屬性不能初始化,因?yàn)樗麤]有支持字段 (backing field)梢什。
為什么拓展屬性不能初始化奠蹬?這個(gè)問題可以轉(zhuǎn)換為 為什么拓展屬性沒有支持字段?

官方說:

實(shí)際上嗡午,擴(kuò)展并不會(huì)真正地往類中插入成員變量罩润。因此,我們沒有一個(gè)有效的方式讓一個(gè)擴(kuò)展屬性擁有backing field翼馆,這就是擴(kuò)展屬性不允許被初始化的原因割以。

那么拓展屬性到底是什么?
Kotlin 可以對(duì)一個(gè)類的屬性和方法進(jìn)行擴(kuò)展应媚,且不需要繼承或使用裝飾器模式严沥。擴(kuò)展是一種靜態(tài)行為,對(duì)被擴(kuò)展的類代碼本身不會(huì)造成任何影響中姜。

因?yàn)椴粫?huì)對(duì)類的代碼本身造成任何影響消玄,所以擴(kuò)展不會(huì)真正的往類中插入成員變量。

field的作用域是當(dāng)前屬性的訪問器丢胚,而當(dāng)前屬性是與某個(gè)類的實(shí)例對(duì)應(yīng)的翩瓜,所以類中并沒有這個(gè)屬性,也就沒有一個(gè)有效的方式讓這個(gè)屬性擁有backing field了携龟。

  • 有field和沒有field的屬性有什么區(qū)別兔跌?

訪問屬性的方式不依賴于它是否含有field,如果你顯式地引用或者使用默認(rèn)的訪問器實(shí)現(xiàn)峡蟋,編譯器會(huì)為屬性生成field坟桅。如果你提供了一個(gè)自定義的訪問器實(shí)現(xiàn)并且沒有使用field华望,支持字段將不會(huì)被呈現(xiàn)出來(lái)。

有時(shí)候不需要修改訪問器的默認(rèn)實(shí)現(xiàn)仅乓,但是需要修改它的可見性:

class LengthCounter {
  var counter: Int = 0
    private set //這個(gè)屬性不能在所在類外部被修改
  fun addWord(word: String) {
    counter += word.length
  }
}

在接口中

在接口中赖舟,可以包含具有setter/getter的屬性,只要他們沒有引用一個(gè)backing field夸楣,
backing field需要在接口中存儲(chǔ)狀態(tài)宾抓,而這是不被允許的


圖片6.png

圖片7.png
支持屬性:功能與backing field相似,能達(dá)到相同的效果:
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // 參數(shù)類型是自動(dòng)推導(dǎo)
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }
參考

https://medium.com/@agrawalsuneet/backing-field-in-kotlin-bd9c2d5b6da5
https://juejin.im/post/5a79c053f265da4e6e2bad37
https://blog.csdn.net/Strange_Monkey/article/details/82707242

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末豫喧,一起剝皮案震驚了整個(gè)濱河市洞慎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嘿棘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旭绒,死亡現(xiàn)場(chǎng)離奇詭異鸟妙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)挥吵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門重父,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人忽匈,你說我怎么就攤上這事房午。” “怎么了丹允?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵郭厌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我雕蔽,道長(zhǎng)折柠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任批狐,我火速辦了婚禮扇售,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嚣艇。我一直安慰自己承冰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布食零。 她就那樣靜靜地躺著困乒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贰谣。 梳的紋絲不亂的頭發(fā)上顶燕,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天凑保,我揣著相機(jī)與錄音,去河邊找鬼涌攻。 笑死欧引,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恳谎。 我是一名探鬼主播芝此,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼因痛!你這毒婦竟也來(lái)了婚苹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸵膏,失蹤者是張志新(化名)和其女友劉穎膊升,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谭企,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廓译,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了债查。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片非区。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖盹廷,靈堂內(nèi)的尸體忽然破棺而出征绸,到底是詐尸還是另有隱情,我是刑警寧澤俄占,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布管怠,位于F島的核電站,受9級(jí)特大地震影響缸榄,放射性物質(zhì)發(fā)生泄漏排惨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一碰凶、第九天 我趴在偏房一處隱蔽的房頂上張望暮芭。 院中可真熱鬧,春花似錦欲低、人聲如沸辕宏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瑞筐。三九已至,卻和暖如春腊瑟,著一層夾襖步出監(jiān)牢的瞬間聚假,已是汗流浹背块蚌。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膘格,地道東北人峭范。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瘪贱,于是被迫代替她去往敵國(guó)和親纱控。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 大家好菜秦,我是William李梓峰甜害,歡迎加入我的Kotlin學(xué)習(xí)之旅。今天是我學(xué)習(xí) Kotlin 的第九天球昨,學(xué)習(xí)內(nèi)容...
    William李梓峰閱讀 684評(píng)論 -3 0
  • Kotlin的類和接口與Java的類和接口是有一定的區(qū)別的主慰。Kotlin的接口是可以包含屬性聲明嚣州。Kotlin默認(rèn)...
    程自舟閱讀 10,317評(píng)論 0 11
  • 最近,一個(gè)同學(xué)突然問到一個(gè)問題:為什么擴(kuò)展屬性不能直接進(jìn)行初始化河哑?針對(duì)這個(gè)問題,官方文檔有一段簡(jiǎn)短的解釋龟虎,翻譯成中...
    歐陽(yáng)鋒閱讀 3,711評(píng)論 1 6
  • 寫在開頭:本人打算開始寫一個(gè)Kotlin系列的教程鲤妥,一是使自己記憶和理解的更加深刻佳吞,二是可以分享給同樣想學(xué)習(xí)Kot...
    胡奚冰閱讀 1,411評(píng)論 5 11
  • 系列文章全部為本人的學(xué)習(xí)筆記,若有任何不妥之處棉安,隨時(shí)歡迎拍磚指正底扳。如果你覺得我的文章對(duì)你有用,歡迎關(guān)注我贡耽,我們一起...
    我愛吃栗子啊閱讀 14,341評(píng)論 3 8