kotlin學(xué)習(xí)第四天

泛型

泛型的定義

泛型是可以在類或方法中預(yù)支地使用未知的類型仓手。泛型的定義有多種,第一種是在定義的時(shí)候在類上面加上泛型聲明业踢,進(jìn)行使用的時(shí)候再確定泛型:

fun main(args: Array<String>) {
    var box = Box<Apple>(Apple())
}

class Box<T>(var thing: T)

class Apple

第二種是定義專門的類繼承泛型類栗柒,確定泛型類型:

fun main(args: Array<String>) {
    AppleBox(Apple())
}

open class Box<T>(var thing: T)

open class AppleBox(thing: Apple) : Box<Apple>(thing)//專門定義AppleBox

class Apple

第三種是父類定義有泛型,子類不知道具體類型知举,還可以再傳遞一個(gè)泛型給它:

class FruitBox<FRUIT>(thing:FRUIT):Box<FRUIT>(thing)

泛型函數(shù)

不僅類可以有類型參數(shù)瞬沦,函數(shù)也可以有。類型參數(shù)要放在函數(shù)名稱之前雇锡。要調(diào)用泛型函數(shù)逛钻,在調(diào)用處函數(shù)名之后指定類型參數(shù)即可:

fun main(args: Array<String>) {
    fanxing("qwe")
}

fun <T> fanxing(thing: T) {
    when (thing) {
        is Int -> println("整形")
        is String -> println("字符串")
        is Char -> println("字符型")
    }
}    

泛型上限

泛型上線是最常見的約束類型,與 Java 的 extends 關(guān)鍵字相對(duì)應(yīng):

fun <T:Comparable<T>>sort(list:List<T>) {}

冒號(hào)之后指定的類型是上界:只有 Comparable<T> 的子類型可以替代 T 锰提。

泛型擦除

在泛型中無法獲取到泛型類型绣的,這叫做泛型擦除。

fun main(args: Array<String>) {
    val box1 = Box<Int>(10)
    val box2 = Box<String>("張三")
    val clz1 = box1.javaClass.name
    val clz2 = box2.javaClass.name
    println(clz1)
    println(clz2)
}
open class Box<T>(var thing: T)

在上面代碼中欲账,box1和box2的泛型類型不一樣,但是打印的結(jié)果是相同的芭概。想要解決這個(gè)問題赛不,需要在泛型前面加上reified,在泛型函數(shù)前加上inline:

inline fun <reified T>parse(thing:T):String{
    return T::class.java.name
}

泛型類型投射

有下面一段代碼:

fun main(args: Array<String>) {
    val list = arrayListOf(Thing())
}

//實(shí)物
open class Thing
//水果
open class Fruit: Thing()
//梨
class Pear: Fruit()

如果我們需要Arraylist里面只能傳遞Fruit或者子類罢洲,可以改為:

fun main(args: Array<String>) {
    val list = arrayListOf(Thing())
    parse(list)
}

fun parse(list:ArrayList<out Fruit>){

}

如果我們需要Arraylist里面只能傳遞Fruit或者父類踢故,可以改為:

fun main(args: Array<String>) {
    val list = arrayListOf(Thing())
    parse(list)
}

fun parse(list:ArrayList<in Fruit>){

}

其中:out 相當(dāng)于java的 ? extends;in 相當(dāng)于java的 ? super惹苗。

星號(hào)投射

如果我們希望ArrayList可以傳遞任何東西殿较,這時(shí)可以使用星號(hào)投射,也就是星投影:

fun main(args: Array<String>) {

}
fun parse(list:ArrayList<*>){

}

代碼中的" * "相當(dāng)于java的 " * "

中綴表達(dá)式

標(biāo)有 infix 關(guān)鍵字的函數(shù)也可以使用中綴表達(dá)式(忽略該調(diào)用的點(diǎn)與圓括號(hào))調(diào)用桩蓉。中綴函數(shù)必須滿足以下要求:

1.必須是成員函數(shù)和擴(kuò)展函數(shù)

2.必須只有一個(gè)參數(shù)

3.不能是可變參數(shù)

fun main(args: Array<String>) {
    var p1 = person("張三",20)
    p1 sayhelloto "李四"
}

class person(var name: String, var age: Int) {
    infix fun sayhelloto(person: String) {
        println("$name 給$person 打招呼")
    }
}

注意:中綴表達(dá)式調(diào)用this不能省略:

    fun hehe() {}
    fun haha() {
        this.hehe()
        //中綴調(diào)用
        this.sayhelloto("王五")
    }
}

類委托
有以下案例:
圍裙媽媽只做飯不洗碗淋纲,小頭爸爸洗碗一次十元,大頭兒子洗碗一次三元院究。圍裙媽媽讓小頭爸爸洗碗本涕,小頭爸爸委托給大頭兒子洗。小頭爸爸和大頭兒子都有洗碗的功能晦闰,但是小頭爸爸把洗碗的能力委托給了大頭兒子實(shí)現(xiàn),這就是類委托。類委托有兩種形式醒串,第一種是指定委托,即只委托給大頭兒子實(shí)現(xiàn):

fun main(args: Array<String>) {
    var big = BigHeadSon()
    var small = SmallHeadFather()
    big.wash()
    small.wash()
}

//實(shí)現(xiàn)洗碗的功能
interface WashPower {
    fun wash()
}

//大頭兒子實(shí)現(xiàn)洗碗的功能
class BigHeadSon : WashPower {
    override fun wash() {
        println("大頭兒子開始洗碗")
    }
}

//小頭爸爸委托大頭兒子洗碗
class SmallHeadFather : WashPower by BigHeadSon()

第二種委托:只要有洗碗功能都可以實(shí)現(xiàn):

fun main(args: Array<String>) {
    var big = BigHeadSon()
    var small = SmallHeadFather(big)
    big.wash()
    small.wash()
}

//實(shí)現(xiàn)洗碗的功能
interface WashPower {
    fun wash()
}

//大頭兒子實(shí)現(xiàn)洗碗的功能
class BigHeadSon : WashPower {
    override fun wash() {
        println("大頭兒子開始洗碗")
    }
}

//小頭爸爸委托大頭兒子洗碗->第一種委托
//class SmallHeadFather : WashPower by BigHeadSon()

class SmallHeadFather(washPower: WashPower):WashPower by washPower

屬性委托

屬性委托就是把屬性的get和set方法委托給其他對(duì)象。

過年時(shí),爺爺奶奶給了大頭兒子壓歲錢,圍裙媽媽替大頭兒子保管肛宋。就屬于屬性委托:

fun main(args: Array<String>) {
    var bigheadson = BigHeadSon()
    bigheadson.money = 100
    println(bigheadson.money)
}

class WeiQunMom {
    //存儲(chǔ)兒子的壓歲錢
    var son = 0//兒子的壓歲錢
    var mom = 0//自己的存錢罐
    //委托壓歲錢的get方法
    operator fun getValue(bigHeadSon: BigHeadSon, property: KProperty<*>): Int {
        return son
    }

    //委托壓歲錢的set方法
    operator fun setValue(bigHeadSon: BigHeadSon, property: KProperty<*>, i: Int) {
        son += 20
        mom += i - 20
    }
}

class BigHeadSon {
    var money: Int by WeiQunMom()
}

加載

惰性加載

需要使用的時(shí)候才加載毁涉,屬于懶加載遇西。用by lazy關(guān)鍵字。惰性加載需要注意以下幾點(diǎn):

1.by lazy用在字段压彭,必須val修飾

2.by lazy返回值在最后一行

3.by lazy只會(huì)加載一次

4.對(duì)象里面也可以使用by lazy

5.惰性加載只要調(diào)用就會(huì)都會(huì)加載,所以在需要的時(shí)候再進(jìn)行加載

fun main(args: Array<String>) {
    println(name)
    println(name)
}

val name by lazy {
    println("執(zhí)行了加載1")
    "加載1"
}

class D {
    val name by lazy {
        println("執(zhí)行了加載2")
        "加載2"
    }
}

輸出結(jié)果是

執(zhí)行了加載1

加載1

加載1

可見:

by lazy只會(huì)初始化一次

by lazy最后一行為返回值

by lazy是線程安全的

延遲加載

延遲加載所用到的關(guān)鍵字是lateinit,不確定具體值,var可變缩功,且獨(dú)立于類單獨(dú)存在:

fun main(args: Array<String>) {
    val person = Person()
    person.name = "張三"
    person.sayHello()
}

lateinit var name: String

class Person {
    //現(xiàn)在不知道name對(duì)應(yīng)的數(shù)據(jù)  后面初始化的時(shí)候才能確定
    //延遲初始化
    lateinit var name: String

    fun sayHello() {
        println(name)
    }
}

這段代碼中的name在person類中沒有賦值,在main方法中才予以賦值。若name沒有賦值跟压,沒有賦值直接訪問會(huì)報(bào)錯(cuò):UninitializedPropertyAccessException茸塞。

擴(kuò)展函數(shù)

擴(kuò)展函數(shù)是在不改變已有類的情況下,為類添加新的函數(shù)倔监。主要是為了替代java中的util類静暂。父類定義的擴(kuò)展函數(shù),子類也可以使用。

fun main(args: Array<String>) {
    //可空類型
    val str: String? = null
    //判斷str是否為空
    var res = str?.IsEmpty() ?: true
}
//給String類型擴(kuò)展了一個(gè)IsEmpty函數(shù)
fun String.IsEmpty(): Boolean {
    return this == null || this.length == 0
}

對(duì)于擴(kuò)展函數(shù)來說吉执,如果通過父類接收鼠证,那么執(zhí)行的是父類的擴(kuò)展函數(shù):

fun main(args: Array<String>) {
    val view = View()
    val button:Button = Button()
    button.onclick()
}
fun View.onclick(){
    println("點(diǎn)擊了view")
}

fun Button.onclick(){
    println("點(diǎn)擊了button")
}
open class View

class Button:View()

object單例

單例的原理:通過靜態(tài)代碼塊創(chuàng)建Person對(duì)象實(shí)例峡竣,用的時(shí)候可以使用這個(gè)實(shí)例。object單例每一個(gè)字段都是靜態(tài)的量九,比較消耗內(nèi)存适掰。object單例適用于成員變量比較少的情況:

fun main(args: Array<String>) {
    Person.sayHello()
    Person.sayHello()
}

object Person{
    var name = "張三"
    var age = "20"
    var phone = "123"
    fun sayHello(){
        println("hello")
    }
}

伴生對(duì)象

可以將定義成static靜態(tài)的屬性放在伴生對(duì)象里,外部類可以直接調(diào)用伴生對(duì)象里面的方法和屬性荠列。伴生對(duì)象的字段都是靜態(tài)的:

class Person{
    var name = "張三"
    companion object {
        var phone = "123444"
    }
}

枚舉

枚舉類的最基本的用法是實(shí)現(xiàn)類型安全的枚舉类浪,枚舉里面保存的就是有限的實(shí)例對(duì)象:

fun todo(week: Week) {
    when (week) {
        Week.星期一 -> println("工作")
        Week.星期二 -> println("工作")
        Week.星期三 -> println("工作")
        Week.星期四 -> println("工作")
        Week.星期五 -> println("工作")
        Week.星期六 -> println("休息")
        Week.星期日 -> println("休息")
    }
}

enum class Week {
    星期一, 星期二, 星期四, 星期五, 星期六, 星期日, 星期三
}

枚舉的高級(jí)用法

以RGB顏色為例:

RED r:255 g:0 b:0

GREEN r:0 g:255 b:0

BLUE r:0 g:0 b:255

fun main(args: Array<String>) {
    println(Color.RED.r)
}

enum class Color(var r:Int,var g:Int,var b:Int){
    RED(255,0,0),GREEN(0,255,0),BLUE(0,0,255)
}

數(shù)據(jù)類

我們經(jīng)常創(chuàng)建一些只保存數(shù)據(jù)的類。 在這些類中肌似,一些標(biāo)準(zhǔn)函數(shù)往往是從數(shù)據(jù)機(jī)械推導(dǎo)而來的费就。在 Kotlin 中,這叫做數(shù)據(jù)類并標(biāo)記為data川队。數(shù)據(jù)類只保存數(shù)據(jù)力细,沒有其他任何邏輯操作,對(duì)應(yīng)java的bean類固额。數(shù)據(jù)類相當(dāng)于提供了bean類的模板眠蚂,可以替代java的bean:

fun main(args: Array<String>) {
    val news = News("d:/path/a.jpg","標(biāo)題","簡(jiǎn)介")
    news.component1()//對(duì)應(yīng)imgPath
    news.component2()//對(duì)應(yīng)title
    news.component3()
}

data class News(var imgPath:String,var title:String,var desc:String)

密封類

密封類可以理解為增強(qiáng)型的枚舉。枚舉在意數(shù)據(jù)斗躏,而密封類更在意類型逝慧。所以,密封類密封的是類型:

fun main(args: Array<String>) {
    println(isLegel(JonSnow()))
}

fun isLegel(stark: NedStark): Boolean {
    when (stark) {
        is NedStark.AryaStark -> return true
        is NedStark.RobStark -> return true
        is NedStark.SansaStark -> return true
        is NedStark.BrandonStark -> return true
        else -> return false
    }
}

sealed class NedStark {
    class RobStark : NedStark()
    class SansaStark : NedStark()
    class AryaStark : NedStark()
    class BrandonStark : NedStark()
}

class JonSnow : NedStark()
class KonSnow : NedStark()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市笛臣,隨后出現(xiàn)的幾起案子云稚,更是在濱河造成了極大的恐慌,老刑警劉巖沈堡,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件静陈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡踱蛀,警方通過查閱死者的電腦和手機(jī)窿给,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來率拒,“玉大人崩泡,你說我怎么就攤上這事♀颍” “怎么了角撞?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)勃痴。 經(jīng)常有香客問我谒所,道長(zhǎng),這世上最難降的妖魔是什么沛申? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任劣领,我火速辦了婚禮,結(jié)果婚禮上铁材,老公的妹妹穿的比我還像新娘尖淘。我一直安慰自己,他們只是感情好著觉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布村生。 她就那樣靜靜地躺著,像睡著了一般饼丘。 火紅的嫁衣襯著肌膚如雪趁桃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天肄鸽,我揣著相機(jī)與錄音卫病,去河邊找鬼。 笑死典徘,一個(gè)胖子當(dāng)著我的面吹牛忽肛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烂斋,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了汛骂?” 一聲冷哼從身側(cè)響起罕模,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帘瞭,沒想到半個(gè)月后淑掌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝶念,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年抛腕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒殉。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡担敌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出廷蓉,到底是詐尸還是另有隱情全封,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布桃犬,位于F島的核電站刹悴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏攒暇。R本人自食惡果不足惜土匀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望形用。 院中可真熱鬧就轧,春花似錦、人聲如沸尾序。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽每币。三九已至携丁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兰怠,已是汗流浹背梦鉴。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揭保,地道東北人肥橙。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像秸侣,于是被迫代替她去往敵國(guó)和親存筏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宠互,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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