Kotlin 知識梳理(4) - 數(shù)據(jù)類宴偿、類委托 及 object 關(guān)鍵字

Kotlin 知識梳理系列文章

Kotlin 知識梳理(1) - Kotlin 基礎(chǔ)
Kotlin 知識梳理(2) - 函數(shù)的定義與調(diào)用
Kotlin 知識梳理(3) - 類、對象和接口
Kotlin 知識梳理(4) - 數(shù)據(jù)類鹤竭、類委托 及 object 關(guān)鍵字
Kotlin 知識梳理(5) - lambda 表達式和成員引用
Kotlin 知識梳理(6) - Kotlin 的可空性
Kotlin 知識梳理(7) - Kotlin 的類型系統(tǒng)
Kotlin 知識梳理(8) - 運算符重載及其他約定
Kotlin 知識梳理(9) - 委托屬性
Kotlin 知識梳理(10) - 高階函數(shù):Lambda 作為形參或返回值
Kotlin 知識梳理(11) - 內(nèi)聯(lián)函數(shù)
Kotlin 知識梳理(12) - 泛型類型參數(shù)


一迫肖、本文概要

本文是對<<Kotlin in Action>>的學(xué)習(xí)筆記,如果需要運行相應(yīng)的代碼可以訪問在線環(huán)境 try.kotlinlang.org闲坎,這部分的思維導(dǎo)圖為:

二疫粥、數(shù)據(jù)類和類委托

2.1 數(shù)據(jù)類:自動生成通用方法的默認實現(xiàn)

在平時的開發(fā)中茬斧,我們往往會使用許多的xxBean對象用作數(shù)據(jù)容器,而在定義這些對象時梗逮,一般會重寫它的以下三個方法:

  • equals:用來比較實例
  • hashCode:用來作為例如HashMap這種基于哈希容器的類
  • toString:用來為類生成按聲明順序排列的所有字段的字符串表達形式

Kotlin中项秉,只需要為你的類添加data關(guān)鍵字,以上這些必要的方法就會自動生成好慷彤,例如下面的例子娄蔼,我們演示了以上三個方法的作用:


運行結(jié)果為:

equalshashCode方法會將所有在主構(gòu)造方法中聲明的屬性納入考慮:

  • equals方法會檢測所有的屬性的值是否相等
  • hashCode方法會返回一個根據(jù)所有屬性生成的哈希值

數(shù)據(jù)類和不可變性

在設(shè)計數(shù)據(jù)類時,應(yīng)當(dāng)盡量只使用只讀的屬性底哗,讓數(shù)據(jù)類的實例不可變岁诉,因為如果不這樣,被用作鍵的對象在加入HashMap或者類似容器后被修改了跋选,容器會進入一種無效的狀態(tài)涕癣。

為了讓使用不可變對象變得容易,Kotlin編譯器為它們生成了copy方法前标,并在copy的同時修改某些屬性的值坠韩,copy出來的副本有著單獨的聲明周期而且不會影響代碼中引用原始實例的位置,使用方法如下:

2.2 類委托

當(dāng)我們需要向一個類添加一些行為時炼列,一般有兩種做法:

  • 繼承這個類只搁,在子類中增加方法
    這種方法的缺點是:當(dāng)系統(tǒng)不斷演進并且基類的實現(xiàn)被修改或者新方法被添加進去時,你做出的關(guān)于類的行為的假設(shè)會失效唯鸭。
  • 使用裝飾器模式
    本質(zhì)是創(chuàng)建一個新類须蜗,實現(xiàn)與原始類一樣的接口并將原來的類的實例作為一個字段保存硅确。與原始類擁有同樣行為的方法不用修改目溉,只需要直接轉(zhuǎn)發(fā)到原始類的實例。這種方法的缺點是:需要相當(dāng)多的樣板代碼菱农。

Kotlin將委托作為一個語言級別的功能做了頭等支持缭付。無論什么時候?qū)崿F(xiàn)一個接口辰斋,你都可以使用by關(guān)鍵字 將接口的實現(xiàn)委托到另一個對象滤否;當(dāng)需要修改某些方法的行為時,可以重寫它們瑰步,這樣你的方法就會被調(diào)用而不是使用生成的方法的妖,可以保留感到滿意的委托給內(nèi)部的實例中的默認實現(xiàn)绣檬。


運行結(jié)果為:

三、object 關(guān)鍵字

object關(guān)鍵字在多種情況下出現(xiàn)嫂粟,它的核心理念為:這個關(guān)鍵字 定義一個類并同時創(chuàng)建一個實例娇未,下面我們介紹它的三個應(yīng)用場景:

  • 對象聲明 是定義單例的一種方式
  • 伴生對象 可以持有工廠方法和其它與這個類相關(guān),但在調(diào)用時并不依賴類實例的方法星虹,它們的成員可以通過類名來訪問零抬。
  • 對象表達式 用來替代Java的匿名內(nèi)部類镊讼。

3.1 對象聲明:創(chuàng)建單例易如反掌

Java中,單例模式通常是使用private構(gòu)造方法平夜,并且用靜態(tài)字段來持有這個類僅有的實例蝶棋。

而在Kotlin中,通過使用對象聲明功能忽妒,將類聲明與該類的單一實例聲明結(jié)合到了一起玩裙。

  • 對象聲明通過object關(guān)鍵字引入,一個對象聲明可以非常高效地以一句話來定義一個類和一個該類的變量段直。
  • 一個對象聲明可以包含屬性献酗、方法、初始化語句塊等的聲明坷牛,但是 不允許聲明構(gòu)造方法罕偎,這是因為對象在定義的時候就已經(jīng)創(chuàng)建了,不需要在其他地方調(diào)用構(gòu)造方法京闰。
  • 對象聲明允許使用對象名加.字符的方式來調(diào)用方法和訪問屬性颜及。

繼承自接口的對象聲明

對象聲明可以繼承自類和接口,這通常在你使用的框架需要去實現(xiàn)一個接口蹂楣,但是你的實現(xiàn)不包含任何狀態(tài)的時候很有用俏站。


在類中聲明對象

在類中使用對象聲明時,這樣的對象同樣只有一個單一實例:它們在每個容器類的實例中具有相同的實例痊土。



運行結(jié)果為:


在 Java 中使用 Kotlin 對象

如果要在Java中使用Kotlin中的聲明對象肄扎,可以通過訪問靜態(tài)的INSTANCE字段:

Kotlin 中的對象聲明

Java 的調(diào)用方式

3.2 伴生對象:工廠方法和靜態(tài)成員的地盤

Kotlin的類不能擁有靜態(tài)成員,作為替代赁酝,Kotlin依賴包級別函數(shù)(在大多數(shù)情形下能夠替代Java的靜態(tài)方法)和對象聲明(在其他情況下替代Java的靜態(tài)方法犯祠,同時還包括靜態(tài)字段),在大多數(shù)情況下酌呆,推薦使用頂層函數(shù)衡载,但是頂層函數(shù)不能訪問類的private變量。

因此隙袁,如果你需要寫一個 在沒有類實例的情況下 調(diào)用但是需要 訪問類內(nèi)部的函數(shù)痰娱,可以將其寫成那個類中的 對象聲明的成員

在類中定義的對象之一可以使用一個特殊的關(guān)鍵字來標(biāo)記 companion菩收,如果這樣做梨睁,就獲得了直接 通過容器類名稱來訪問這個對象的方法和屬性的能力,不再需要顯示地指明對象的名稱娜饵,下面是一個基礎(chǔ)的示例:


運行的結(jié)果為:

使用工廠方法創(chuàng)建對象

下面是使用伴生對象來實現(xiàn)工廠方法的例子:


3.3 作為普通對象使用的伴生對象

伴生對象是一個聲明在類中的普通對象坡贺,它可以有名字,實現(xiàn)一個接口或者有擴展函數(shù)或?qū)傩浴<僭O(shè)我們需要在對象和JSON之間進行序列化和反序列化拴念,可以將序列化的邏輯放在伴生對象中钧萍。


運行結(jié)果為:

在大多數(shù)情況下,通過包含伴生對象的類的名字(也就是例子中的Person類)來引用伴生對象政鼠,所以不必關(guān)心它的名字风瘦,如果省略了伴生對象的名字,默認的名字將會分配為Companion公般。

在伴生對象中實現(xiàn)接口

就像其它對象聲明一樣万搔,伴生對象也可以實現(xiàn)接口,可以將包含它的類的名字當(dāng)做實現(xiàn)了該接口的對象實例來使用官帘。



運行結(jié)果為:


伴生對象擴展

Kotlin 知識梳理(2) - 函數(shù)的定義與調(diào)用 中瞬雹,我們介紹了通過擴展函數(shù),可以通過代碼庫中其它地方定義類實例調(diào)用的方法刽虹,但是如果你需要定義可以通過 類自身調(diào)用的方法酗捌,就像伴生對象方法或者Java靜態(tài)方法該怎么辦呢?

舉例來說涌哲,如果類有一個伴生對象胖缤,可以通過在其上定義擴展函數(shù)來做到這一點,即類C有一個伴生對象阀圾,并且在C.Companion上定義了一個擴展函數(shù)func哪廓,則可以通過C.fun()來調(diào)用它。

下面初烘,我們?yōu)?code>Person類的伴生對象定義一個擴展函數(shù):

當(dāng)調(diào)用toJson就像是它是一個伴生對象定義的方法一樣涡真,但是實際上它是作為擴展函數(shù)在外部定義的。而為了能夠為你的類定義擴展肾筐,必須在其中聲明一個對象哆料,即使是空的。

3.4 對象表達式:改變寫法的匿名內(nèi)部類

object關(guān)鍵字不僅能夠用來表明單例式的對象局齿,還能用來聲明 匿名對象剧劝,它替代了Java中匿名內(nèi)部類的用法橄登。例如抓歼,讓我們來看看怎樣將一個典型的匿名內(nèi)部類用法轉(zhuǎn)換成Kotlin


運行結(jié)果為:

將匿名對象存儲到變量中

除了去掉對象的名字外,語法與對象聲明相同的拢锹。對象表達式聲明了一個類并創(chuàng)建了該類的一個實例谣妻,但是沒有給這個類或是實例分配一個名字。通常來說卒稳,它們都是不需要名字的蹋半,因為你會將這個對象用作一個函數(shù)調(diào)用的參數(shù)。如果你需要給對象分配一個名字充坑,可以將其存儲到一個變量中:


在對象表達式中修改變量的值

Java的匿名類一樣减江,在對象表達式中的代碼可以訪問創(chuàng)建它的函數(shù)中的變量染突,但是與Java不同,訪問并被限制在final變量辈灼,還可以在對象表達式中修改變量的值份企。


運行結(jié)果為:


更多文章,歡迎訪問我的 Android 知識梳理系列:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巡莹,一起剝皮案震驚了整個濱河市司志,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌降宅,老刑警劉巖骂远,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腰根,居然都是意外死亡激才,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門额嘿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贸营,“玉大人,你說我怎么就攤上這事岩睁〕” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵捕儒,是天一觀的道長冰啃。 經(jīng)常有香客問我,道長刘莹,這世上最難降的妖魔是什么阎毅? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮点弯,結(jié)果婚禮上扇调,老公的妹妹穿的比我還像新娘。我一直安慰自己抢肛,他們只是感情好狼钮,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捡絮,像睡著了一般熬芜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上福稳,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天涎拉,我揣著相機與錄音,去河邊找鬼。 笑死鼓拧,一個胖子當(dāng)著我的面吹牛半火,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播季俩,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼慈缔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了种玛?” 一聲冷哼從身側(cè)響起藐鹤,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赂韵,沒想到半個月后娱节,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡祭示,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年肄满,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片质涛。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡稠歉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汇陆,到底是詐尸還是另有隱情怒炸,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布毡代,位于F島的核電站阅羹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏教寂。R本人自食惡果不足惜捏鱼,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酪耕。 院中可真熱鬧导梆,春花似錦、人聲如沸迂烁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婚被。三九已至狡忙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間址芯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谷炸,地道東北人北专。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像旬陡,于是被迫代替她去往敵國和親拓颓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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

  • 前言 人生苦多描孟,快來 Kotlin 驶睦,快速學(xué)習(xí)Kotlin! 什么是Kotlin匿醒? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,145評論 9 118
  • Kotlin的類和接口與Java的類和接口是有一定的區(qū)別的廉羔。Kotlin的接口是可以包含屬性聲明溉痢。Kotlin默認...
    程自舟閱讀 10,317評論 0 11
  • 不重要的廢話 前段時間看了一遍《Programming Kotlin》,主要目的是想提高自己的英文閱讀能力憋他,能力提...
    珞澤珈群閱讀 3,333評論 1 7
  • Kotlin 知識梳理系列文章 Kotlin 知識梳理(1) - Kotlin 基礎(chǔ)Kotlin 知識梳理(2) ...
    澤毛閱讀 2,470評論 0 4
  • “姐姐孩饼,民間的上元節(jié)是什么樣子的?” 鴻兒伸手在李下玉面前虛晃竹挡,打斷了她的沉思镀娶。此刻她們置身在一個狹小的屋子里,姐...
    陶然吶閱讀 342評論 1 0