[4] —— Kotlin 數(shù)據(jù)類勒奇、解構(gòu)聲明與單例模式-簡(jiǎn)單即是美

在之前的三篇文章中直秆,我們已經(jīng)了解了一下的內(nèi)容:

  1. 如何在項(xiàng)目中使用 Kotlin濒募,Kotlin 的空安全
  2. 集合的相關(guān)操作,擴(kuò)展函數(shù)以及 Lambda 表達(dá)式等高級(jí)特性
  3. for 與集合遍歷圾结,強(qiáng)大的 if 瑰剃、when 表達(dá)式,可以用來做單例模式的伴生對(duì)象

1筝野、數(shù)據(jù)類

你是否已經(jīng)厭煩了一個(gè)項(xiàng)目中大量的 POJO 晌姚?是的,雖然我們有大量的插件來幫助我們簡(jiǎn)化這些創(chuàng)建過程歇竟,但是滿天的 gettersetter 還有那些 equals()/hashCode() 大量機(jī)械的挥唠、重復(fù)的方法,早已讓我們厭煩不堪途蒋。

Kotlin 為我們提供了更強(qiáng)大數(shù)據(jù)類猛遍,如下所示:

data class User(var name: String="", var age:Int = 0){
    var nickname:String = ""
}

使用 data 關(guān)鍵字來告知系統(tǒng)這是一個(gè)數(shù)據(jù)類,其主構(gòu)造函數(shù)需要至少有一個(gè)參數(shù)号坡,如果生成的類需要含有一個(gè)無(wú)參的構(gòu)造函數(shù)懊烤,則所有的屬性必須指定默認(rèn)值。

請(qǐng)注意宽堆,對(duì)于那些自動(dòng)生成的函數(shù)腌紧,編譯器只使用在主構(gòu)造函數(shù)內(nèi)部定義的屬性。如需在生成的實(shí)現(xiàn)中排出一個(gè)屬性畜隶,請(qǐng)將其聲明在類體中壁肋。

自動(dòng)生成的函數(shù)只是用主構(gòu)造函數(shù)定義的屬性

1.1、復(fù)制一個(gè)數(shù)據(jù)類

復(fù)制數(shù)據(jù)類的兩個(gè)方式

當(dāng)我們使用 copy 函數(shù)時(shí)籽慢,系統(tǒng)會(huì)找到該類的主構(gòu)造函數(shù)的簽名浸遗,此時(shí)我們可以按順序填入?yún)?shù)(無(wú)需完全填寫,會(huì)從第一位開始自動(dòng)匹配)箱亿,還可以采用類似 Python 的方式 參數(shù)名 = 值的方式來修改我們需要的參數(shù)值跛锌。

2、解構(gòu)聲明

這四個(gè)字對(duì)于 Android + Java 開發(fā)者是挺陌生的届惋,大家可以點(diǎn)擊到 Kotlin 中文站查看詳細(xì)的定義髓帽,下面我們通過代碼來了解一下他的用法,首先我們來看一張熟悉的圖:


for 循環(huán)遍歷 Map 集合

注意這里的 (k,v) 這就是一個(gè)解構(gòu)聲明脑豹,標(biāo)準(zhǔn)庫(kù)已經(jīng)幫我們實(shí)現(xiàn)了解構(gòu)聲明郑藏,另外數(shù)據(jù)類也已經(jīng)實(shí)現(xiàn)了主構(gòu)造函數(shù)包含參數(shù)的解構(gòu)聲明。

比如剛剛我們創(chuàng)建的 User 類瘩欺,我們可以通過如下的方式來獲取其中指定的值:

var (name,age) = c
var (_,aged) = d  //用下劃線占位不需要的參數(shù)
var aged1 = d.component2()  //直接使用 componentN 函數(shù)來獲取對(duì)應(yīng)的值
println("c's name = $name c's age = $age")
println("don't need d's name, d's age = $aged")
println("other way to get d's age is $aged1")

我們可以任意的在類中進(jìn)行解構(gòu)聲明必盖,比如我們可以使用解構(gòu)聲明來擴(kuò)展剛剛我們定義的 User 類:

data class User(var name: String="", var age:Int = 0){
    var nickname:String = ""

    operator fun component3() = nickname
}

需要注意的是拌牲,數(shù)據(jù)類默認(rèn)為我們實(shí)現(xiàn)了主構(gòu)造函數(shù)的參數(shù)解構(gòu)聲明,所以我們的解構(gòu)聲明只能接著主構(gòu)造函數(shù)的序號(hào)往后使用

自定義的解構(gòu)聲明

2.1筑悴、在 Lambda 表達(dá)式中使用解構(gòu)聲明

當(dāng)這個(gè)類進(jìn)行了解構(gòu)聲明時(shí)们拙,我們可以直接在 Lambda 表達(dá)式中使用其解構(gòu)稍途,如下:

c.let { (a,b,c) ->
            println("c's name = $a , c's age = $b , c's nickname = $c")
        }

請(qǐng)注意解構(gòu)聲明對(duì)于 Lambda 表達(dá)式而言是一個(gè)參數(shù):

{ a //-> …… } // 一個(gè)參數(shù)
{ a, b //-> …… } // 兩個(gè)參數(shù)
{ (a, b) //-> …… } // 一個(gè)解構(gòu)對(duì)
{ (a, b), c //-> …… } // 一個(gè)解構(gòu)對(duì)以及其他參數(shù)

在函數(shù)中返回?cái)?shù)個(gè)參數(shù)

有的時(shí)候我們經(jīng)常會(huì)希望一個(gè)函數(shù)能返給我們多個(gè)結(jié)果阁吝,例如曾經(jīng)我做過一個(gè)小功能:傳入 PM2.5 的值,返回當(dāng)前 PM2.5 嚴(yán)重程度的介紹以及需要顯示的顏色代碼械拍。當(dāng)時(shí)我采用的做法是返回一個(gè) Map突勇,然后再需要的地方在使用固定的 key 將值提取出來,這一點(diǎn)也不優(yōu)雅坷虑。

但是在 Kotlin 里 你可以這樣做:

    fun getPM25DescAndColor(pm25: Int):Pair<String,String> {
        return when (pm25) {
            in 0..50 -> Pair("優(yōu)秀","#009900")
            in 51..100 -> Pair("良好","#FFCC33")
            in 101..150 -> Pair("輕度","#FF9900")
            in 151..200 -> Pair("中度","#FF3300")
            in 201..300 -> Pair("重度","#9900FF")
            else -> Pair("嚴(yán)重","#663300")
        }
    }

標(biāo)準(zhǔn)庫(kù)提供了 PairTriple 這兩個(gè)類甲馋,前者表示兩個(gè)參數(shù),后者表示三個(gè)參數(shù)迄损。盡管在很多情況下命名數(shù)據(jù)類是更好的設(shè)計(jì)選擇定躏, 因?yàn)樗鼈兺ㄟ^為屬性提供有意義的名稱使代碼更具可讀性。

3芹敌、單例模式

不要在考慮單例模式的幾種寫法了痊远,也不要在關(guān)注什么線程安全、線程不安全了氏捞。

不知道你有沒有疑惑過碧聪,Java 是一個(gè)面向?qū)ο缶幊痰恼Z(yǔ)言(OOP),但是 Java 里有些東西似乎不那么 OOP液茎,比如單例模式逞姿,又比如公共靜態(tài)方法。這兩者都必須在一個(gè) class 下面捆等,他們卻都不應(yīng)該是一個(gè)類滞造。一個(gè)單例模式,既然是一個(gè) class 為什么不能處處實(shí)例化它栋烤?一個(gè)個(gè)公共靜態(tài)方法谒养,調(diào)用它為什么還要先寫一個(gè) class?這并不符合直覺班缎!

Kotlin 幫我們徹底的解決了這一迷思蝴光!本篇我們先來說說在 Kotlin 里如何寫好一個(gè)單例模式。

在 Java 里我最常用的單例模式是靜態(tài)內(nèi)部類达址,因?yàn)樗词蔷€程安全又是懶加載的蔑祟,我們來看一下一個(gè)最簡(jiǎn)單的靜態(tài)內(nèi)部類單例模式:

public class Singleton {

    //構(gòu)造方法私有
    private Singleton() {
    }

    //在訪問HttpMethods時(shí)創(chuàng)建單例
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }

    //獲取單例
    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

我們通過私有的構(gòu)造函數(shù)來使得外部類不能創(chuàng)建這個(gè)類的實(shí)例,在私有的內(nèi)部靜態(tài)類中實(shí)例化這個(gè)類沉唠,然后提供一個(gè)公共靜態(tài)訪問內(nèi)部類中的成員疆虚。

我們來看看這樣一個(gè)單例我們?cè)?Kotlin 中應(yīng)該如何處理:

object Singleton {
    fun doSomething(){
    }
}

是的就是這么簡(jiǎn)單,我們只要使用 object 關(guān)鍵字就可以聲明一個(gè)單例,這是真正意義上的單例径簿,因?yàn)樗旧砭褪且粋€(gè)對(duì)象罢屈!在 Kotlin 中這被稱作對(duì)象聲明,就像變量聲明一樣篇亭,對(duì)象聲明不是一個(gè)表達(dá)式缠捌,不能用在賦值語(yǔ)句的右邊。

對(duì)象聲明的初始化過程是線程安全的译蒂。

如需引用該對(duì)象曼月,我們直接使用其名稱即可:

Singleton.doSomething()

如果你只是在某個(gè) kt 文件中需要使用一個(gè)單例模式的對(duì)象,我們還可以使用 object 關(guān)鍵字來實(shí)現(xiàn) Java 中的匿名內(nèi)部類:

var e = object {
    fun print(index: Int): String {
        return "你輸入的數(shù)字是:$index"
    }
}
println(e.print(34))

當(dāng)然這個(gè)對(duì)象還可存在繼承與實(shí)現(xiàn):

open class A(x: Int) {
    public open val y: Int = x
}

interface B {……}

val ab: A = object : A(1), B {
    override val y = 15
}

PS:誠(chéng)如本篇文章的標(biāo)題柔昼,簡(jiǎn)單就是美哑芹,Kotlin 中還有很多這樣充滿美感的設(shè)計(jì)或是語(yǔ)法糖,請(qǐng)繼續(xù)關(guān)注后續(xù)文章捕透!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聪姿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子乙嘀,更是在濱河造成了極大的恐慌末购,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乒躺,死亡現(xiàn)場(chǎng)離奇詭異招盲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嘉冒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門曹货,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讳推,你說我怎么就攤上這事顶籽。” “怎么了银觅?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵礼饱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我究驴,道長(zhǎng)镊绪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任洒忧,我火速辦了婚禮蝴韭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熙侍。我一直安慰自己榄鉴,他們只是感情好履磨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庆尘,像睡著了一般剃诅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驶忌,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天矛辕,我揣著相機(jī)與錄音,去河邊找鬼位岔。 笑死如筛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抒抬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晤柄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼擦剑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芥颈,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惠勒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后爬坑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纠屋,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年盾计,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了售担。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡署辉,死狀恐怖族铆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哭尝,我是刑警寧澤哥攘,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站材鹦,受9級(jí)特大地震影響逝淹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桶唐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一栅葡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莽红,春花似錦妥畏、人聲如沸邦邦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)燃辖。三九已至,卻和暖如春网棍,著一層夾襖步出監(jiān)牢的瞬間黔龟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工滥玷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氏身,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓惑畴,卻偏偏與公主長(zhǎng)得像蛋欣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子如贷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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