屬性和域

屬性和域

什么是屬性文兢?
實(shí)際是指getter和setter方法扑毡,雖然和字段是兩個(gè)概念,姑且可以理解為有g(shù)etter和setter方法的字段窟赏。
如何聲明?
完整語(yǔ)法:

var 屬性名: <屬性類(lèi)型> [= <初始化器>]
    [<getter>]
    [<setter>]

其中的初始化器别凤、getter和setter方法是可選的饰序。如果沒(méi)有自定義getter和setter的實(shí)現(xiàn),就會(huì)使用默認(rèn)的规哪。
以下兩種情況屬性類(lèi)型也可省略:

  1. 可以通過(guò)初始化器推斷出來(lái)
  2. 被聲明的屬性會(huì)覆蓋基類(lèi)中的屬性求豫,并且通過(guò)基類(lèi)中屬性的類(lèi)型推動(dòng)出來(lái)

兩種屬性:
只讀屬性:val關(guān)鍵字聲明
可變屬性:var關(guān)鍵字聲明
訪問(wèn)屬性:
訪問(wèn)屬性使用點(diǎn)操作符,對(duì)象名.屬性名诉稍,如:

var person = Person()
person.name = "張三"

和oc一樣蝠嘉,點(diǎn)操作符內(nèi)部的實(shí)現(xiàn)也是調(diào)用getter或setter訪問(wèn)器。并且在Kotlin中訪問(wèn)Java的屬性時(shí)杯巨,仍然可以用點(diǎn)語(yǔ)法訪問(wèn)Java對(duì)象中的屬性蚤告。

如果要修改訪問(wèn)器的可見(jiàn)性或添加注解,但又不需要修改默認(rèn)實(shí)現(xiàn)服爷,你可以重新定義方法杜恰,但不定義它的實(shí)現(xiàn),這樣仍然是使用默認(rèn)實(shí)現(xiàn)仍源。如:

var setterVisibility: String = "abc"
    private set // 設(shè)值方法的可見(jiàn)度為 private, 并使用默認(rèn)實(shí)現(xiàn)

var setterWithAnnotation: Any? = null
    @Inject set // 對(duì)設(shè)值方法添加 Inject 注解

屬性的后端域變量(Backing Field)

Kotlin類(lèi)不能擁有域變量(也就是Java中的成員變量)心褐,但是使用訪問(wèn)器時(shí)又需要這種域變量,所以Kotlin提供了后端域變量笼踩,可以用field標(biāo)識(shí)符來(lái)訪問(wèn)逗爹。
如:

var counter = 0 // 初始化給定的值將直接寫(xiě)入后端域變量中
    set(value) {
        if (value >= 0) field = value
    }
  }

field就代表編譯器自動(dòng)生成的后端域變量,并且只允許在屬性訪問(wèn)器中使用

什么情況下會(huì)生成后端域變量嚎于?

  1. 訪問(wèn)器中任一個(gè)使用默認(rèn)實(shí)現(xiàn)
  2. 自定義的訪問(wèn)器中通過(guò)field關(guān)鍵字訪問(wèn)屬性

下面這種情況下就不會(huì)生成后端域變量:

val isEmpty: Boolean
    get() = this.size() == 0 //自定義訪問(wèn)器沒(méi)有使用field關(guān)鍵字訪問(wèn)屬性

為什么不用this關(guān)鍵字訪問(wèn)屬性呢掘而?
試想下,this代表當(dāng)前對(duì)象于购,而上面說(shuō)過(guò)通過(guò)點(diǎn)操作符袍睡,訪問(wèn)屬性時(shí),實(shí)際上是調(diào)用了訪問(wèn)器肋僧,在訪問(wèn)器內(nèi)部實(shí)現(xiàn)中再調(diào)用訪問(wèn)器就會(huì)出現(xiàn)無(wú)限遞歸女蜈。所以持舆,通過(guò)Backing Filed可以避免這個(gè)問(wèn)題色瘩。

后端屬性(Backing Property)

如果你的操作是想訪問(wèn)屬性內(nèi)部的屬性伪窖,或者集合里面的元素,而不是屬性本身居兆,那么你可以聲明這個(gè)屬性為private的(后端屬性)覆山,然后定義個(gè)public的屬性并自定義其訪問(wèn)器,在自定義的訪問(wèn)器內(nèi)部訪問(wèn)后端屬性泥栖。如:

private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        // 這里的操作不希望屬于 backing filed簇宽,
        if (_table == null) {
            _table = HashMap() 
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }

其實(shí)也沒(méi)有什么神秘的,其實(shí)就像Java中我們通常寫(xiě)的吧享,在訪問(wèn)私有屬性時(shí)魏割,在自定義訪問(wèn)器中添加些限制,避免取到或設(shè)置非法的值一個(gè)道理钢颂。只是在Kotlin中取了個(gè)高大上的名字钞它。

編譯器常數(shù)值

值在編譯期就能確定的屬性,用const關(guān)鍵字修飾殊鞭。滿足以下條件的屬性可以標(biāo)記為編譯器常數(shù)值:

  1. 必須是頂級(jí)屬性或是object的成員
  2. 值必須是String或基本類(lèi)型
  3. 不能自定義取值方法

如:

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

編譯器常數(shù)值可以用在注解內(nèi):

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

延遲初始化屬性

通常屬性被聲明為非null類(lèi)型就必須就地初始化遭垛。但是,這種限制在很多情況下是不方便的操灿,比如锯仪,聲明的屬性通過(guò)依賴注入的方式來(lái)初始化。這種情況下趾盐,你就可以使用lateinit關(guān)鍵字來(lái)修飾聲明的屬性庶喜。
如:

public class MyTest {
    lateinit var subject: TestSubject

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

    @Test fun test() {
        subject.method()  // 直接訪問(wèn)屬性
    }
}

使用限制:

  1. 只能用于var屬性
  2. 只能用于類(lèi)體內(nèi)聲明的屬性
  3. 屬性不能有自定義訪問(wèn)器
  4. 屬性必須是非null
  5. 屬性不能是基本類(lèi)型
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市救鲤,隨后出現(xiàn)的幾起案子久窟,更是在濱河造成了極大的恐慌,老刑警劉巖蜒简,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘸羡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡搓茬,警方通過(guò)查閱死者的電腦和手機(jī)犹赖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)卷仑,“玉大人峻村,你說(shuō)我怎么就攤上這事∥” “怎么了粘昨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我张肾,道長(zhǎng)芭析,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任吞瞪,我火速辦了婚禮馁启,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芍秆。我一直安慰自己惯疙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布妖啥。 她就那樣靜靜地躺著霉颠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荆虱。 梳的紋絲不亂的頭發(fā)上蒿偎,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音克伊,去河邊找鬼酥郭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愿吹,可吹牛的內(nèi)容都是我干的不从。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼犁跪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼椿息!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起坷衍,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寝优,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后枫耳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乏矾,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年迁杨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钻心。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铅协,死狀恐怖捷沸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狐史,我是刑警寧澤痒给,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布说墨,位于F島的核電站,受9級(jí)特大地震影響苍柏,放射性物質(zhì)發(fā)生泄漏尼斧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一序仙、第九天 我趴在偏房一處隱蔽的房頂上張望突颊。 院中可真熱鬧,春花似錦潘悼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至糙申,卻和暖如春宾添,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柜裸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工缕陕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疙挺。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓扛邑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親铐然。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔬崩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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