基本類型

類和對象

類和繼承

Kotlin中使用關(guān)鍵字class聲明類

class Person{
}

類的聲明由類名類頭(指定類的類型參數(shù)犀忱、主構(gòu)造函數(shù)等)和類體(后面花括號包圍的部分)得院;如果一個類沒有類體左电,可以省略花括號牌废。

class Person

構(gòu)造函數(shù)

在Kotlin中一個類可以有一個主構(gòu)造函數(shù)和一個或多個次構(gòu)造函數(shù)咽白。主構(gòu)造函數(shù)是類頭的一部分:它跟在類名(和可選的類型參數(shù))后。

class Person constructor(firstName: String){
}

如果主構(gòu)造函數(shù)沒有任何的注解和可見性修飾符鸟缕,可以省略constructor關(guān)鍵字晶框。

class Person(firstName: String){
}

主構(gòu)造函數(shù)不包含任何代碼。初始化代碼可以放在以init關(guān)鍵字作為前綴的初始化塊(initializer block)中:

class Customer(name: String) { 
    init {
        logger.info("Customer initialized with value ${name}") 
    }
}

注意主構(gòu)造函數(shù)的參數(shù)可以在初始化塊中使用懂从。也可以在類體內(nèi)聲明屬性時授段,在屬性的初始化器中使用:

class Customer(name: String){
    init{
        logger.info("Customer initialized with value ${name}") //在初始化塊中使用主構(gòu)造函數(shù)的參數(shù)
    }
    val customerKey = name.toUpperCase()//在屬性的初始化器中使用主構(gòu)造函數(shù)的慘是

}

其實,聲明屬性以及從主構(gòu)造函數(shù)初始化屬性番甩,Kotlin有更簡潔的語法:

class Person(
    val firstName: String, 
    val lastName: String, 
    var age: Int) { 
        // ......
}

與普通在類內(nèi)部聲明的屬性一樣侵贵,主構(gòu)造函數(shù)中聲明的屬性也可以是可變(var)或只讀(val)。
如果主構(gòu)造函數(shù)有注解或可見性修飾符缘薛,則關(guān)鍵字constructor不能省略模燥,并且修飾符在其前面:

class Customer public @Inject constructor(name: String){
    //do some thing
}

次構(gòu)造函數(shù)

類也可是聲明前綴有constructor次構(gòu)造函數(shù)

class Person{
    constructor(parent: Person){
        parent.chilren.add(this)
    }
}

如果類有主構(gòu)造函數(shù),每個次構(gòu)造函數(shù)都需要委托給主構(gòu)造函數(shù)掩宜,可以直接委托或者通過別的次構(gòu)造函數(shù)間接委托。委托到同一個類的另一個構(gòu)造函數(shù)用this關(guān)鍵字即可:

class Person(val name: String){
    constructor(name: String,parent: Person) : this(name){
        parent.children.add(this)
    }
}

如果一個類非抽象并且沒有聲明任何(主或次)構(gòu)造函數(shù)么翰,它會默認生成一個無參的主構(gòu)造函數(shù)牺汤。并且這個默認無參構(gòu)造函數(shù)的可見性為public。如果你不希望你的類有一個公有的構(gòu)造函數(shù)浩嫌,你需要聲明一個帶飛默認可見性的空主構(gòu)造函數(shù):

class DontCreatMe private constructor(){
}

在JVM上檐迟,如果主構(gòu)造函數(shù)的所有參數(shù)都有默認值,編譯器會生成一個額外的無參構(gòu)造函數(shù)码耐,它將使用默認值追迟,這使得Kotlin更易于使用像Jackson或JPA這樣通過無參構(gòu)造函數(shù)創(chuàng)建類的實例的庫。

class Customer(val customerName: String = "")

創(chuàng)建類的實例

要創(chuàng)建類的實例骚腥,我們只需要像調(diào)用普通函數(shù)一樣調(diào)用構(gòu)造函數(shù):

val user = User()
val customer = Customer("Jon Smith")

可以發(fā)現(xiàn)Kotlin中創(chuàng)建類的實例,是不需要new關(guān)鍵字的,Kotlin中也沒有這個關(guān)鍵字

類成員

  • 構(gòu)造函數(shù)和初始化塊
  • 函數(shù)
  • 屬性
  • 嵌套類和內(nèi)部類
  • 對象聲明

繼承

在Kotlin中所有類都有一個共同的超類Any偷拔,所有類都直接或間接派生自這個類,類似Java中的Object

class Example (){//默認派生自Any
}

但是厢绝,Any并不是java.lang.Object;它除了equalshasCode()带猴、toString()外沒有其它成員昔汉。
要繼承一個類,我們把超類放到派生類的類頭的冒號后面:

open class Base(p: Int)
class Derived(p: Int) : Base(p)

如果子類有一個主構(gòu)造函數(shù)拴清,其基類可以并且必須用子類主構(gòu)造函數(shù)的參數(shù)就地初始化靶病。
若子類沒有主構(gòu)造函數(shù),那么每個次構(gòu)造函數(shù)必須使用super關(guān)鍵字初始化其基類型口予,或委托另一個構(gòu)造函數(shù)間接做到這一點娄周。注意,在這種情況下苹威,不同的次構(gòu)造函數(shù)可以調(diào)用基類型的不同的構(gòu)造函數(shù)

class MyView : View{
    constructor(ctx: Context) : super(ctx)
    constructor(ctx: Context,attrs: AttributeSet):super(ctx,attrs)
}

在Kotlin中昆咽,open標注與Java中的final相反,它標注的類才允許被其他類繼承牙甫。默認情況下掷酗,在Kotlin中所有的類都是final的,這正對應(yīng)了Effective Java中的要么為繼承而設(shè)計窟哺,并提供文檔說明泻轰,要么禁止繼承。

覆蓋方法

在Kotlin中力求清晰顯式且轨。與Java不同浮声,Kotlin中需要顯式標注可以被覆蓋的成員(或稱開放的成員)和覆蓋后的成員:

open class Base {
    open fun v(){} //可以被復寫的成員用open標注
    fun nv(){}
}
class Derived() : Base(){
   final override fun v(){} //復寫后的成員用override標注,默認override標注的成員也是開放的旋奢,如果想再次限制其被覆蓋可以顯式的用final標注
}

覆蓋屬性

屬性覆蓋和方法覆蓋類似泳挥;在子類中聲明超類中的同名屬性就是覆蓋超類中的屬性,并且必須以override開頭作為標注至朗,并且它們的類型必須兼容屉符。每個聲明的屬性可以由具有初始化器的屬性或者具有getter方法的屬性覆蓋。

open class Foo{
    open val x: Int锹引?= null
        get(){//重寫get方法
            field = 100
            return field
        }
}
class Bar1 : Foo(){
    override val x: Int? = null
}

在Kotlin中矗钟,屬性都有默認的getset方法嫌变,并且可以被重寫吨艇,如上面的例子。如果子類中覆蓋了父類中的屬性腾啥,那么在父類中重寫的被覆蓋屬性的get方法东涡,在子類中是無效的冯吓。

val可以被var覆蓋
但是var不能被val覆蓋

覆蓋規(guī)則

如果一個類從它的直接超類繼承相同成員的多個實現(xiàn),那么這個類必須必須覆蓋這個成員并提供自己的實現(xiàn)(或者用繼承來的其中之一)软啼。為了表示采用從哪個超類中繼承的實現(xiàn)桑谍,我們使用super<Base>表示:

open class A {
    open fun f() { 
        print("A") 
    } 
    fun a() { 
        print("a") 
    }
}
interface B {
    fun f() { 
        print("B") 
    } // 接口成員默認就是“open”的,并且可以有實現(xiàn)
    fun b() { 
        print("b") 
    }
}
class C() : A(), B {
    // 編譯器要求覆蓋 f(): 
    override fun f() {
        super<A>.f() // 調(diào)用 A.f()
        super<B>.f() // 調(diào)用 B.f() 
    }
}

C同時繼承了兩個不同f()實現(xiàn),所以必須在C中覆蓋f()并且提供自己的實現(xiàn)來消除歧義祸挪。

抽象類

類和其中某些成員可以聲明為abstract的锣披。抽象成員在本類中可以不實現(xiàn)。抽象類默認是開放的贿条,不需要用open關(guān)鍵字標注雹仿。并且我們可以用一個抽象成員覆蓋一個非抽象的開放成員

open class Base{
    open fun f(){}
}
abstract class Derived : Base(){
    override abstract fun f()
}

伴生對象

在Kotlin中沒有靜態(tài)方法。在大多數(shù)情況下整以,它建議采用包級函數(shù)(在類外面與包在一個級別)胧辽。
如果你需要寫一個無需類的實例來調(diào)用,但需要訪問類內(nèi)部的的函數(shù)公黑,你可以把它寫成該類內(nèi)對象聲明中的一員邑商,而不是類本身的成員。
這里說的類內(nèi)聲明的對象凡蚜,就是伴生對象人断,伴生對象內(nèi)聲明的成員只需要類名作為限定符就可以訪問,語法與Java/C#中調(diào)用靜態(tài)方法一樣朝蜘。

封閉類或密封類

用來限制類的繼承恶迈,可以限制給定的某個對象只可能是某些指定的類型之一。有點像枚舉谱醇。枚舉類的值是有限的暇仲,每個枚舉值常數(shù)都代表枚舉類的一個實例,而密封類允許的子類類型是有限的副渴,但每個子類的實例數(shù)并未做限制奈附。
如何聲明密封類?

  1. 使用sealed修飾符放在class關(guān)鍵字之前煮剧;
  2. 子類聲明必須嵌套在密封類聲明部分之內(nèi)桅狠;

如:

sealed class Expr {
    class Const(val number:Double):Expr()
    class Sum(val e1: Expr,val e2: Expr):Expr()
    object NotAnumber : Expr()//這里聲明的是個單利類
}

用途:
when表達式中可以驗證分支語句覆蓋了所有條件,避免使用else分支處理例外情況轿秧。

sealed class Expr {
    class Const(val number:Double):Expr()
    class Sum(val e1: Expr,val e2: Expr):Expr()
    object NotAnumber : Expr()
}

是否還有其他更有用的用途呢?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咨堤,一起剝皮案震驚了整個濱河市菇篡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌一喘,老刑警劉巖驱还,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗜暴,死亡現(xiàn)場離奇詭異,居然都是意外死亡议蟆,警方通過查閱死者的電腦和手機闷沥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咐容,“玉大人舆逃,你說我怎么就攤上這事〈亮#” “怎么了路狮?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔚约。 經(jīng)常有香客問我奄妨,道長,這世上最難降的妖魔是什么苹祟? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任砸抛,我火速辦了婚禮,結(jié)果婚禮上树枫,老公的妹妹穿的比我還像新娘直焙。我一直安慰自己,他們只是感情好团赏,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布箕般。 她就那樣靜靜地躺著,像睡著了一般舔清。 火紅的嫁衣襯著肌膚如雪丝里。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天体谒,我揣著相機與錄音杯聚,去河邊找鬼。 笑死抒痒,一個胖子當著我的面吹牛幌绍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播故响,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼傀广,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了彩届?” 一聲冷哼從身側(cè)響起伪冰,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎樟蠕,沒想到半個月后贮聂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體靠柑,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年吓懈,在試婚紗的時候發(fā)現(xiàn)自己被綠了歼冰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡耻警,死狀恐怖隔嫡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榕栏,我是刑警寧澤畔勤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站扒磁,受9級特大地震影響庆揪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妨托,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一缸榛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兰伤,春花似錦内颗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至符衔,卻和暖如春找前,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背判族。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工躺盛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人形帮。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓槽惫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辩撑。 傳聞我的和親對象是個殘疾皇子界斜,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

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