Kotlin的解析(中)

前言

??通過上一篇的Kotlin介紹了一些基本的變量煞聪,方法鸠澈,函數(shù),類等的基本講解层释,接下來婆瓜,讓我們更近一步的學習,深入一點的知識

1.??枚舉類和擴展

1.1?枚舉類

??Kotlin的枚舉類和Java的非常相似贡羔,具有類的特性廉白,一般會將可枚舉的同類型一組值作為枚舉類定義,由于每一枚舉都是個對象,可能在性能上還是不推薦用乖寒,Android中已經(jīng)用注解慢慢取代了猴蹂,這種枚舉的使用

1.1.1 枚舉類的基本用法

??在kotlin中,枚舉類型是以類的形式存在的楣嘁,因此成為枚舉類

enum class Direction {
NORTH,SOUTH,WEST,EAST
}

1.1.2 枚舉值指定對應的數(shù)值
??從下面的代碼可以看出磅轻,除了基本的語法不同,實現(xiàn)的規(guī)則和Java的非常相似

enum class Direction private constructor(val d:Int){ 
    SOUTH(1),WEST(2);

    override fun toString(): String {
        return d.toString()
    }
}

fun main(args:Array<String>){
var dir1 : Direction = Direction. SOUTH
var dir2  = Direction. WEST
println(dir1)//輸出的是1
println(dir2)//輸出的是2
}

1.1.3 枚舉的其他拓展

  var dir1 : Direction = Direction. WEST
        Log.i("tag",dir1.name)//輸出的是:WEST
        Log.i("tag",dir1.ordinal.toString()) //輸出的是在枚舉中的位置 1
        Log.i("tag",dir1.toString()) //輸出的是傳入的數(shù)值
        Log.i("tag",Direction.valueOf("WEST").toString()) //輸出的是傳入的數(shù)值

//如果要得到所有枚舉的值逐虚,可以使用values的方法
for(d in Direction.values()){
println(d)
}
1.2?擴展

??擴展是Kotlin中非常重要的功能聋溜,可以在沒有源代碼的情況下向類中添加成員,也可以啊子團隊開發(fā)的情況下叭爱,通過擴展撮躁,將模塊分散給多個人開發(fā)

1.2.1 擴展原生API

Kotlin的原生的集合擴展

//這個方法放哪里呢?一般都放在Kotlin文件頂層买雾,當然把曼,也可以放在調(diào)用swap方法的位置前面
fun MutableList<Int>.swap(index1:Int ,index2:Int){
            //為MutableList添加一個swap的方法杨帽,用于交互任意兩個集合元素的位置
            var tmp = this[index1]
            this[index1] = this[index2]
            this[index2] = tmp;
        }

val tab = mutableListOf(1,2,3)
        tab.swap(0,2) //原生里面是沒有這個方法的,通過擴展就可以了嗤军,牛逼
        Log.i("tag","jihe:  " + tab.toString())//輸出[3,2,1]

JDK標準的集合類ArrayList添加了一個hellow的方法

 fun ArrayList<Int>.hellow(string: String){
            println(string)
        }

        var list: ArrayList<Int> = ArrayList();
        list.add(20)
        list.add(30)
        list.add(40)
        list.add(50)
        list.swap(0,2)//這個是原生自帶的
        list.hellow("牛逼吧W⒂!型雳!嘻嘻") //這個是上面自己寫的一個方法

1.2.2 擴展自定義類
??擴展類的目的很多当凡,除了系統(tǒng)類需要擴展之外,我們自己編寫的類有時候也需要擴展纠俭,但是我們有不想去類里面修改沿量,這時候這個功能就相得益彰

open class Parent(val va1: Int, val va2: Int) {//使用open聲明,才能允許其他類繼承
    var mVal1 = va1
    var mVal2 = va2
    fun add() = this.mVal1 + this.mVal2
}

class Child(va1: Int, va2: Int) : Parent(va1, va2) {
    fun sub() = mVal1 - mVal2
}


        fun Parent.log() {
            Log.i("tag", "父類:" + "${mVal1} +${mVal2} = ${add()}")
        }

        fun Child.log() {
            Log.i("tag", "子類:" + "${mVal1} -${mVal2} = ${sub()}")
        }

        var par1: Parent = Parent(1, 2)
        var par2: Parent = Child(1, 2)
        var chil1: Child = Child(1, 2)

        par1.log()//父類:1 +2 = 3
        par2.log()//父類:1 +2 = 3
        chil1.log()//子類:1 -2 = -1



open class Parent(val va1: Int, val va2: Int) {
    var mVal1 = va1
    var mVal2 = va2
    fun add() = this.mVal1 + this.mVal2
//內(nèi)部成員函數(shù)冤荆,和擴展同名朴则,擴展覆蓋不了內(nèi)部
fun log() {
        Log.i("tag", "父類:自己" + "${mVal1} +${mVal2} = ${add()}")
    }
}


fun Parent.log() {
            Log.i("tag", "父類:" + "${mVal1} +${mVal2} = ${add()}")
        }

        fun Child.log() {
            Log.i("tag", "子類:" + "${mVal1} -${mVal2} = ${sub()}")
        }

        var par1: Parent = Parent(1, 2)
        var par2: Parent = Child(1, 2)
        var chil1: Child = Child(1, 2)

        par1.log()//父類:自己1 +2 = 3
        par2.log()//父類:自己1 +2 = 3
        chil1.log()//父類:自己1 +2 = 3
 

??上面可以看出:(1)盡管par2的實例對象是Child,但是通過擴展的方法钓简,并沒有重寫父類的擴展方法乌妒,因此par2調(diào)用的還是父類的方法。
(2)類內(nèi)部成員函數(shù)和通過擴展添加的成員函數(shù)沖突外邓,那么內(nèi)部成員函數(shù)的優(yōu)先級更高撤蚊,通過擴展無法覆蓋內(nèi)部成員函數(shù)

1.2.3 擴展伴隨對象
??如果類中有伴隨對象(由于Kotlin類不支持靜態(tài)成員變量,因此引入了伴隨對象损话,來解決類沒有靜態(tài)成員所帶來的尷尬)侦啸,那么可以利用擴展對象添加成員

class SubClass  {
    companion object {
    }
}

fun  SubClass.Companion.nihao(){
           Log.i("tag","hello word!")
        }

SubClass.nihao();//不需要實例,直接類名調(diào)用
//擴展范圍丧枪,放大
//在類中也可以使用擴展

2.??數(shù)據(jù)類和封裝

??數(shù)據(jù)類和封裝是Kotlin中兩種特殊的類光涂,前者用于描述數(shù)據(jù)和相應的操作,后者相當于枚舉類的擴展拧烦,用于描述有限的數(shù)據(jù)

2.1?數(shù)據(jù)類

??數(shù)據(jù)類是Kotlin 的一個語法糖忘闻,Kotlin編譯器會自動為數(shù)據(jù)類生產(chǎn)一些成員函數(shù),以提高開發(fā)效率

2.1.1 使用數(shù)據(jù)類

//一般的類的書寫
class User(var name: String, var sex: Int)  {
    var mName = name
    var mSex = sex
    override fun equals(other: Any?): Boolean {
    //重寫恋博,是不是感覺的很不爽齐佳,要寫這么多
        if (other is User) {
            if (mName == other.mName && mSex == other.mSex) {
                return true
            }
        } else {
            return false
        }
        return false
    }
    override fun toString(): String {
      //重寫,是不是Java中很煩债沮,yes炼吴,很煩
        return "User {name = $mName \n sex = $mSex }"
    }
}

??從上面User可以看出,只有name和sex是必要的秦士,其余的都可以自動的推倒,而怎么弄呢永高?其實Kotlin中提供了隧土,那就是在class前面加上data關(guān)鍵字就行了

data class Student(var name: String) {
    constructor():this("sdfdf")//為了添加一個無參的構(gòu)造函數(shù)
}

var student = Student("xixi")
var student1 = Student("haha")
Log.i("tag", student.toString()); //輸出:Student(name=xixi)
Log.i("tag", student1.toString());//輸出: Student(name=haha)
Log.i("tag", student.equals(student1).toString());//輸出:false

??數(shù)據(jù)類和普通的類最大的不同提针,就是數(shù)據(jù)類可以根據(jù)構(gòu)造器的參數(shù)自動生成相關(guān)的代碼;如果Kotlin中曹傀,同事具有普通類辐脖,以及存儲和管理數(shù)據(jù)的功能,建議直接使用數(shù)據(jù)類

編寫數(shù)據(jù)類注意事項
(1)主構(gòu)造器至少有一參數(shù)
(2)主構(gòu)造器的參數(shù)必須標記為var/val
(3)數(shù)據(jù)類不能是抽象類皆愉,open類嗜价,封閉類(sealed)類或內(nèi)部類(inner)
由于主構(gòu)造器必須要有一個參數(shù),不可能存在沒有參數(shù)的主構(gòu)造器幕庐,要想擁有久锥,兩種方案解決:
(1)為主構(gòu)造器每個參數(shù)都加上默認值

data class User(val name :String="Bill", var age :Int = 10)

(2)添加一個沒有參數(shù)的構(gòu)造器,調(diào)用主構(gòu)造器時异剥,指定默認參數(shù)

data class User(var name : String ,var age :Int){
//次構(gòu)造函數(shù)
constructor():this("Devin","18")
}

2.1.2 數(shù)據(jù)類成員的解構(gòu)
??數(shù)據(jù)類成員解構(gòu)瑟由,這里關(guān)鍵解構(gòu),也就是解除結(jié)構(gòu)冤寿,在數(shù)據(jù)類中歹苦,用屬性表示數(shù)據(jù),這些屬性屬于同一數(shù)據(jù)類督怜,要想使用這些屬性,必須首先引用數(shù)據(jù)對象蚪腋,這里的解構(gòu)就是指將這些數(shù)據(jù)對象的屬性提取出來究流,分別單獨賦值給變量

  var student = Student("大家好")
  val (name) = student
  Log.i("tag", ";;;;;;"+name );//;;;;;;大家好

2.1.3 封閉類
??封閉類也是Kotlin的一個語法糖辣吃,可以把它理解為枚舉的擴展,一個封閉類芬探,前面用sealed,可以有任意多個字對象神得,封閉類的值只能是這些字對象偷仿,使用封閉類的好處,主要是與when表達式配合酝静,不需要再使用else形式

sealed class Icon ()
class Small() : Icon()
class Big() : Icon()

fun eval(icon: Icon) {
        when (icon) {
            is Small -> {
            }
            is Big -> {
            }
        }
    }

var big = Big()
        eval(big)

3.??泛型

3.1?泛型基礎(chǔ)

??所謂的泛型节榜,就是指在定義數(shù)據(jù)結(jié)構(gòu)時,只指定類型的占位符别智,等到使用該數(shù)據(jù)結(jié)構(gòu)時在指定具體的數(shù)據(jù)類型

class Box<T>(t :T){
    var value = t
}

var box = Box<Int>(1)
Log.i("tag", ";;;;;;" + box.value);
3.2?類型變異

??Kotlin泛型并沒有提供通配符,取而代之的是out和in的關(guān)鍵字(1)用out聲明的泛型占位符只能用在獲取泛型類型值的地方(2)用in聲明的泛型只能在設(shè)置泛型類型值的地方

(1). 使用out關(guān)鍵字

abstract class Source< out T> {
   abstract fun NextT(): T
}

fun demo(strs: Source<String>) {
//編譯通過讳窟,因為T是一個out類型參數(shù)
    val ni: Source<Any> = strs
    
}

(1).使用in關(guān)鍵字

abstract class Comparable<in T>{
    abstract fun comparaTo(other:T)
}

fun demo (x:Comparable<Number>){
//1.0時Double類型,Double時Number的子類型
    x.comparaTo(1.0)
    val y: Comparable<Double> = x
}
3.3?泛型函數(shù)
 fun <T> single(item :T) :T{
        return item
    }

var single = single(1)
 Log.i("tag", ";;;;;;" + single);
3.4?泛型約束

??最常見的約束是上界(upper bound),與Java的extends關(guān)鍵字相同,如果沒有指定丽啡,默認使用的上界類型Any?,在定義泛型參數(shù)的尖括號內(nèi),只允許定義唯一一個上界改执,要是多個就的使用where

fun <T :Parent> convert(item :T){
}

fun<T>clone (list:List<T>,there:T):List<T> where T :Comparable,T:Cloneable{
//.....
}

總結(jié)

??通過本章節(jié)的學習坑雅,了解到了枚舉類,數(shù)據(jù)類霞丧,封閉類,泛型后豫,而且學到了非常方便的一個擴展的實用語法突那,可以很方便的為原生Api以及其他類擴充方法,比較靈活方便愕难,也希望此篇幅的知識對你有稍許的幫助

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猫缭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子猜丹,更是在濱河造成了極大的恐慌,老刑警劉巖射窒,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脉顿,死亡現(xiàn)場離奇詭異,居然都是意外死亡艾疟,警方通過查閱死者的電腦和手機敢辩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門责鳍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兽间,“玉大人正塌,你說我怎么就攤上這事∨曳蹋” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵讼育,是天一觀的道長稠集。 經(jīng)常有香客問我,道長痹籍,這世上最難降的妖魔是什么晦鞋? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮悠垛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斤讥。我一直安慰自己拇惋,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布蓉坎。 她就那樣靜靜地躺著胡嘿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拓瞪,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天助琐,我揣著相機與錄音,去河邊找鬼蛆橡。 笑死掘譬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的葱轩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垃喊,長吁一口氣:“原來是場噩夢啊……” “哼袜炕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耕突,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤评架,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后纵诞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡登刺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年纸俭,在試婚紗的時候發(fā)現(xiàn)自己被綠了南窗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郎楼。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡窒悔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出简珠,到底是詐尸還是另有隱情,我是刑警寧澤荐操,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布珍策,位于F島的核電站宅倒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蹭劈。R本人自食惡果不足惜线召,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缓淹。 院中可真熱鬧,春花似錦料仗、人聲如沸伏蚊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胜卤,卻和暖如春赁项,著一層夾襖步出監(jiān)牢的瞬間是鬼,已是汗流浹背紫新。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芒率,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓充择,卻偏偏與公主長得像匪蟀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子观挎,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 前言 人生苦多段化,快來 Kotlin ,快速學習Kotlin雄嚣! 什么是Kotlin喘蟆? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,211評論 9 118
  • 面向?qū)ο缶幊蹋∣OP) 在前面的章節(jié)中,我們學習了Kotlin的語言基礎(chǔ)知識封锉、類型系統(tǒng)膘螟、集合類以及泛型相關(guān)的知識成福。...
    Tenderness4閱讀 4,444評論 1 6
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔奴艾,今天18年5月份再次想寫文章内斯,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,762評論 2 9
  • 夜靜滿天星像啼,酒闌人未醒潭苞。 出神偏不覺,入夢似曾經(jīng)此疹。 拂影月千戶,落花香半庭蝗碎。 不知何處鳥,侵曉隔窗聽慈省。
    雪窗_武立之閱讀 776評論 0 8
  • 早起眠菇,于朋友圏發(fā)現(xiàn)一個很有意思的公眾號“早晚簽到”。 又發(fā)現(xiàn)一早己下載卻未常用的App即正在使用的“簡書”...
    簡單愛780324閱讀 197評論 1 1