Kotlin -面向?qū)ο?/h1>

kotlin中的類

class Bird{
  val weight:Double = 500.0
  val color:String = "blue"
  val age:Int = 1
  fun fly(){}
}

上面代碼反編譯成Java的版本后欢瞪,會有g(shù)et方法淌实,除此之外還有一些不同
1)不可變屬性成員沃斤。這是利用java中的final修飾符來實現(xiàn)的鬼譬,使用var聲明屬性則引用可變陨瘩。
2)屬性默認(rèn)值腕够。Java中的屬性有默認(rèn)值,kotlin中舌劳,除非顯試的聲明延遲初始化帚湘,不然就需要指定屬性的默認(rèn)值。
3)不同的可訪問修飾符甚淡。kotlin中默認(rèn)是public大诸,而Java中默認(rèn)是 default

可帶有屬性和默認(rèn)方法的接口

Kotlin中的接口

interface Flyer{
  val speed:Int
  fun kind()
  fun fly(){println("I can fly")}
}

kotlin中的接口是不能像java那樣直接賦值的 不過可以通過get方法來實現(xiàn)

interface Flyer{
    val speed:Int
      get() = 100
}

如果 接口中沒有初始化,則需要在子類中重寫進行初始化

class parot() :Bird {
    override val speed: Int
        get() =101
}

有了類就需要構(gòu)造方法
kotlin中可以通過構(gòu)造方法默認(rèn)參數(shù) 實現(xiàn)構(gòu)造方法重載
舉個??

class Bird(val weight:Double = 0.00,val age:Int = 1)

如果用Java來實現(xiàn)同樣的效果 需要幾個構(gòu)造方法贯卦? 4個资柔。
構(gòu)造方法中可以用val 和var來聲明構(gòu)造方法的參數(shù),val代表引用不可變 撵割,那么在構(gòu)造方法中用val修飾這個變量還能被賦值嗎贿堰,當(dāng)然可以。聲明后代表在類的內(nèi)部聲明了一個同名的屬性,類似一下實現(xiàn)

class Bird(weight:Double = 0.0,age:Int= 0){
  val weight:Double
  val age: Int
  init{
      this.weight = weight
      this.age = age
}
}

上面的代碼很有意思啡彬,說明kotlin也可以分開初始化官边,還有用val 修飾的變量是在初始化之后不可變沸手。
init語句塊 是構(gòu)造方法的一部分,兩者在表現(xiàn)形式上是分離的注簿,如果在初始化時進行其他的額外操作契吉,那么我們就可以使用init語句塊來執(zhí)行 。

構(gòu)造方法的參數(shù)可以在init語句中訪問诡渴,也可以用于初始化類內(nèi)部的屬性成員的情況

class Bird(weight:Double = 0.00){
    val weight:Double = weight
}

但是不能在成員函數(shù)中訪問

class Bird(weight:Double){
  fun printWeight(){
    print(weight) // 這里不能直接訪問 weight
}
}

主從構(gòu)造方法

我們可能需要從一個特殊的數(shù)據(jù)來獲取構(gòu)造類的參數(shù)值捐晶,這時候如果可以定義一個額外的構(gòu)造方法,接收一個自定義的參數(shù)會顯的特別方便

class Bird(val age:Int){
 constructor(birth:DateTime) :this(getAgeByBirth(birth)){}
}

類外部定義的構(gòu)造方法被稱為主構(gòu)造方法妄辩,每個類可最多存在一個主構(gòu)造方法惑灵,和多個從構(gòu)造方法,如果主構(gòu)造方法存在注解或者可見星修飾符眼耀,則constructor 關(guān)鍵字不可省略英支。從構(gòu)造方法會先執(zhí)行對其他構(gòu)造方法的委托,然后執(zhí)行自身代碼塊的邏輯; 如果存在主構(gòu)造方法 那么每個從構(gòu)造方法都要直接或者間接的委托給它哮伟。

不同的訪問控制原則

繼承雖然靈活干花,但是如果被濫用會引起一些問題。舉個?? 我認(rèn)為企鵝也是一種鳥楞黄, 于是聲明了一個Penguin類來繼承Bird

open class Bird{
  open fun fly(){ print("I can fly.")}
}
class Penguin :Bird(){
  override fun fly(){
    print("I can't  fly actually")
}
}

kotlin中的繼承是用:池凄,kotlin中類和方法默認(rèn)是不可被繼承或重寫的,所以必須加上open 修飾符鬼廓。上面的例子明顯不太好肿仑,所以kotlin中默認(rèn)類和方法都是加了final修飾的

sealed

用sealed修飾的類 不能被初始化,因為他背后是基于一個抽象類實現(xiàn)的碎税,若要繼承則需要將子類定義在用一個文件中(同一個包也不行尤慰,就是同一個文件)

可見性修飾符

  1. kotlin與Java的默認(rèn)修飾符不同,kotiin中是public 雷蹂,而Java中是default
    2)kotlin中有個獨特的修飾符internal (模塊內(nèi)可見)
    3)kotlin可以在一個文件內(nèi)單獨聲明方法以及常量伟端,同樣支持可見性修飾
    4)Java中除了內(nèi)部類可以用private修飾以外,其他類都不允許private修飾萎河,而kotlin可以
    5)protected的訪問訪問范圍不同荔泳,Java中是包,類子類虐杯,而kotlin中只允許類及子類玛歌。

模塊內(nèi)訪問(internal)

  • 一個Eclipse項目
  • 一個Intellij IDEA項目
  • 一個Maven項目
  • 一個Grandle項目
  • 一組由一次Ant任務(wù)執(zhí)行編譯的代碼

inner

kotlin中的內(nèi)部類默認(rèn)是static 的,所以想要定義一一個內(nèi)部類 要加上inner關(guān)鍵字
(如果不加則沒有外部類的引用擎椰,無法訪問外部類的屬性和方法)

通過委托來代替多繼承實現(xiàn)需求

interface CanFly{
    fun fly()
}

interface CanEat{
    fun eat()
}

class Flyer:CanFly {
    override fun fly() {
        println("i can fly")
    }
}

class  Animal: CanEat{
    override fun eat() {
        println(" i can eat")
    }
}

class Bird(flyer:Flyer,animal: Animal) :CanFly by flyer ,CanEat by animal

object Test{
    @JvmStatic
    fun main(args: Array<String>) {
        val flyer = Flyer()
        val animal = Animal()
        val bird = Bird(flyer,animal)
        bird.eat()
        bird.fly()
    }
}

疑問:首先支子,委托方式怎么跟接口實現(xiàn)多繼承如此相似,而且好像也沒有簡單多少达舒,其次值朋,這種方式好像跟組合也很像叹侄,那么它到底有什么優(yōu)勢呢?只要有以下亮點:
1)接口是無狀態(tài)的昨登,所以即使它提供了默認(rèn)方法實現(xiàn)也是很簡單的趾代,不能實現(xiàn)復(fù)雜邏輯(也不推薦) 我們可以利用上面委托的這種方式,雖然他也是接口委托丰辣,但是是用一個具體的類去實現(xiàn)方法邏輯撒强,可以擁有更強大的邏輯
2)假設(shè)我們需要繼承的類是A,委托對象是B笙什,C飘哨,我們在具體調(diào)用的時候并不是像組合一樣A.B.method,而是可以直接調(diào)用A.medthod,這樣更能表達A擁有該mehod的能力琐凭,更加直觀

真正的數(shù)據(jù)類

有這樣一種場景芽隆,我們并不想要那么強大的類,也許我們只是想要單純的使用類來封裝數(shù)據(jù)统屈,類似于Java中的DTO(Data transfer object)的概念胚吁,但是我們知道在Java中顯的繁瑣,因為通常情況下我們會聲明一個javaBean鸿吆,然后定義一堆getter和setter囤采。但是你很可能已經(jīng)厭煩了這些冗長的代碼述呐,那來看看kotlin是如何改進這個問題的吧

用data class 創(chuàng)建數(shù)據(jù)類

data class 顧名思義就是數(shù)據(jù)類

data class Bird(var weight:Double ,var age:Int,var color:String)

那么 這個data關(guān)鍵字幫我們做了哪些事情
1)提供get set方法
2)重寫了toString 方法惩淳,重寫equals 和hashcode
3)提供了一些方法 如 copy 和componentN

        val b1 = Bird(3.0,1)
        val b2 = b1.copy(age = 2)

copy 內(nèi)部實現(xiàn)是通過傳過來的參數(shù)重新new了一個對象
接下來我們看看componentN方法。簡單來說乓搬,componentN可以理解為類屬性的值思犁,其中N代表屬性的順序,比如component1代表第一個屬性的值进肯,那么這樣設(shè)計到底有什么用呢激蹲? 我們來思考一個問題,我們或多或少的知道怎么將屬性綁定到類上江掩,到那時如何將類的屬性綁定到相應(yīng)變量上卻不是很熟悉 如:

 // 普通方式
        val b1 = Bird(3.0,1,Color.BLACK)
        val weight = b1.weight
        val age = b1.age
        val color = b1.color
        
        //kotlin 進階
        val (weight,age,color) = b1

只有提供了component函數(shù)的時候才可以這么寫
看到kotlin的語法信息你一定會感到興奮学辱,因為你可能寫過類似下面的代碼

String birdInfo = "20.0,1,bule";
String[] temps = birdInfo.split(".")
double weight = Double.valueOf(temps[0]);
int age = Integer.valueOf(temps[1]);
String color = temps[2];

這樣的代碼有時真的很繁瑣,我們明明知道值的情況环形,卻要分好幾步來給變量賦值策泣,很幸運,kotlin提供了更優(yōu)雅的做法:

val (weight,age,color) = birdInfo.split(".")

這里的原理就是解構(gòu)抬吟,通過編譯器的約定實現(xiàn)解構(gòu)萨咕,kotlin對數(shù)組的結(jié)構(gòu)有一定限制,在數(shù)組中它默認(rèn)最多允許賦值5個變量
自己實現(xiàn)對應(yīng)屬性的componentN方法火本,如:

// 
data class Bird(val weight:Double,val age:Int,val color: Color){
    var sex = 1
    operator fun component4() = sex

    constructor(weight: Double,age: Int, color: Color,sex:Int):this(weight, age, color){
        this.sex = sex
    }

}

//使用
val b1 = Bird(3.0,1,Color.BLACK危队,1)
val (weight,age,color,sex) = b1

除了數(shù)組支持解構(gòu)外聪建,kotlin也提供了其他常用的數(shù)據(jù)類,分別是Pair和Triple,使用如下

val(weightT,ageT,colorT) = Triple(20.0,1,Color.BLUE)

伴生對象

半生對象的設(shè)計目的就是為了把普通變量和靜態(tài)變量區(qū)別開茫陆,而不是混在一個類中靠static關(guān)鍵字區(qū)別金麸。

關(guān)于object關(guān)鍵字

兩個作用
1.天生的單例(餓漢式,線程安全)
2.寫匿名內(nèi)部類

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末簿盅,一起剝皮案震驚了整個濱河市钱骂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挪鹏,老刑警劉巖见秽,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異讨盒,居然都是意外死亡解取,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門返顺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禀苦,“玉大人,你說我怎么就攤上這事遂鹊≌穹Γ” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵秉扑,是天一觀的道長慧邮。 經(jīng)常有香客問我,道長舟陆,這世上最難降的妖魔是什么误澳? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮秦躯,結(jié)果婚禮上忆谓,老公的妹妹穿的比我還像新娘。我一直安慰自己踱承,他們只是感情好倡缠,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茎活,像睡著了一般昙沦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妙色,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天智润,我揣著相機與錄音襟沮,去河邊找鬼类咧。 笑死,一個胖子當(dāng)著我的面吹牛芍碧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播号俐,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼泌豆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吏饿?” 一聲冷哼從身側(cè)響起踪危,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猪落,沒想到半個月后贞远,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡笨忌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年蓝仲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官疲。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡袱结,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出途凫,到底是詐尸還是另有隱情垢夹,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布维费,位于F島的核電站果元,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掩完。R本人自食惡果不足惜噪漾,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一硼砰、第九天 我趴在偏房一處隱蔽的房頂上張望且蓬。 院中可真熱鬧,春花似錦题翰、人聲如沸恶阴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冯事。三九已至,卻和暖如春血公,著一層夾襖步出監(jiān)牢的瞬間昵仅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摔笤,地道東北人够滑。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像吕世,于是被迫代替她去往敵國和親彰触。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

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