基本類型

類和對象

類和繼承

Kotlin中使用關鍵字class聲明類

class Person{
}

類的聲明由類名類頭(指定類的類型參數、主構造函數等)和類體(后面花括號包圍的部分);如果一個類沒有類體,可以省略花括號。

class Person

構造函數

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

class Person constructor(firstName: String){
}

如果主構造函數沒有任何的注解和可見性修飾符,可以省略constructor關鍵字。

class Person(firstName: String){
}

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

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

注意主構造函數的參數可以在初始化塊中使用。也可以在類體內聲明屬性時,在屬性的初始化器中使用:

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

}

其實,聲明屬性以及從主構造函數初始化屬性,Kotlin有更簡潔的語法:

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

與普通在類內部聲明的屬性一樣,主構造函數中聲明的屬性也可以是可變(var)或只讀(val)。
如果主構造函數有注解或可見性修飾符,則關鍵字constructor不能省略,并且修飾符在其前面:

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

次構造函數

類也可是聲明前綴有constructor次構造函數

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

如果類有主構造函數,每個次構造函數都需要委托給主構造函數,可以直接委托或者通過別的次構造函數間接委托。委托到同一個類的另一個構造函數用this關鍵字即可:

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

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

class DontCreatMe private constructor(){
}

在JVM上,如果主構造函數的所有參數都有默認值,編譯器會生成一個額外的無參構造函數,它將使用默認值,這使得Kotlin更易于使用像Jackson或JPA這樣通過無參構造函數創建類的實例的庫。

class Customer(val customerName: String = "")

創建類的實例

要創建類的實例,我們只需要像調用普通函數一樣調用構造函數:

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

可以發現Kotlin中創建類的實例,是不需要new關鍵字的,Kotlin中也沒有這個關鍵字

類成員

  • 構造函數和初始化塊
  • 函數
  • 屬性
  • 嵌套類和內部類
  • 對象聲明

繼承

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

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

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

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

如果子類有一個主構造函數,其基類可以并且必須用子類主構造函數的參數就地初始化。
若子類沒有主構造函數,那么每個次構造函數必須使用super關鍵字初始化其基類型,或委托另一個構造函數間接做到這一點。注意,在這種情況下,不同的次構造函數可以調用基類型的不同的構造函數

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

在Kotlin中,open標注與Java中的final相反,它標注的類才允許被其他類繼承。默認情況下,在Kotlin中所有的類都是final的,這正對應了Effective Java中的要么為繼承而設計,并提供文檔說明,要么禁止繼承。

覆蓋方法

在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覆蓋

覆蓋規則

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

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

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

抽象類

類和其中某些成員可以聲明為abstract的。抽象成員在本類中可以不實現。抽象類默認是開放的,不需要用open關鍵字標注。并且我們可以用一個抽象成員覆蓋一個非抽象的開放成員

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

伴生對象

在Kotlin中沒有靜態方法。在大多數情況下,它建議采用包級函數(在類外面與包在一個級別)。
如果你需要寫一個無需類的實例來調用,但需要訪問類內部的的函數,你可以把它寫成該類內對象聲明中的一員,而不是類本身的成員。
這里說的類內聲明的對象,就是伴生對象,伴生對象內聲明的成員只需要類名作為限定符就可以訪問,語法與Java/C#中調用靜態方法一樣。

封閉類或密封類

用來限制類的繼承,可以限制給定的某個對象只可能是某些指定的類型之一。有點像枚舉。枚舉類的值是有限的,每個枚舉值常數都代表枚舉類的一個實例,而密封類允許的子類類型是有限的,但每個子類的實例數并未做限制。
如何聲明密封類?

  1. 使用sealed修飾符放在class關鍵字之前;
  2. 子類聲明必須嵌套在密封類聲明部分之內;

如:

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()
}

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容