Kotlin 中級(jí)篇(七):抽象類(abstract)顾腊、內(nèi)部類(嵌套類)

一、抽象類

  • 我們知道挖胃,在實(shí)際的開發(fā)程序的時(shí)候杂靶,一般都會(huì)寫一個(gè)基類,封裝常用方法酱鸭、以及處理一些共有的邏輯吗垮,但是程序邏輯是根據(jù)每個(gè)類不同的功能實(shí)現(xiàn)不同的代碼。而這個(gè)所謂的基類凹髓,一般都是一個(gè)抽象類烁登。不管是Java還是Kotlin,實(shí)現(xiàn)其抽象類的作用就在于此蔚舀。那么什么是抽象類呢饵沧,它是怎么定義的,它又要怎么使用呢赌躺?

1狼牺、抽象類的定義

抽象類,可以理解為類定義了一個(gè)模板礼患。所有的子類都是根據(jù)這個(gè)模板是填充自己的代碼是钥。

1.1、關(guān)鍵字

  • 聲明一個(gè)抽象(類或函數(shù))的關(guān)鍵字為:abstract

其中值得注意的是:抽象可以分為抽象類缅叠、抽象函數(shù)悄泥、抽象屬性。而一個(gè)抽象類和普通類的區(qū)別在于抽象類除了可以有其自己的屬性肤粱、構(gòu)造函數(shù)弹囚、方法等組成部分,還包含了抽象函數(shù)以及抽象屬性狼犯。

例:

abstract class Lanauage{
    val TAG = this.javaClass.simpleName  // 自身的屬性

    // 自身的函數(shù)
    fun test() : Unit{
        // exp
    }
    abstract var name : String           // 抽象屬性
    abstract fun init()                  // 抽象方法
}

/**
 * 抽象類Lanauage的實(shí)現(xiàn)類TestAbstarctA
 */
class TestAbstarctA : Lanauage(){

    override var name: String
        get() = "Kotlin"
        set(value) {}

    override fun init() {
        println("我是$name")
    }
}

/**
 * 抽象類Lanauage的實(shí)現(xiàn)類TestAbstarctB
 */
class TestAbstarctB : Lanauage(){
    override var name: String
        get() = "Java"
        set(value) {}

    override fun init() {
        println("我是$name")
    }
}

fun main(args: Array<String>) {

    // val lanauage = Lanauage() 是錯(cuò)誤的余寥,因?yàn)槌橄箢惒荒苤苯颖粚?shí)例化

    val mTestAbstarctA = TestAbstarctA()
    val mTestAbstarctB = TestAbstarctB()

    println(mTestAbstarctA.name)
    mTestAbstarctA.init()

    println(mTestAbstarctB.name)
    mTestAbstarctB.init()
}

輸出結(jié)果為:

Kotlin
我是Kotlin
Java
我是Java

1.2领铐、小結(jié)

  • 抽象類本身具有普通類特性,以及組成部分宋舷。不過值得注意的是绪撵,抽象類不能直接被實(shí)例化
  • 其抽象了類的子類必須全部重寫帶abstract修飾的屬性和方法。
  • 抽象成員只有定義祝蝠,沒有實(shí)現(xiàn)音诈。都有abstract修飾符修飾。
  • 抽象類是為其子類定義了一個(gè)模板绎狭。不同是類實(shí)現(xiàn)不同的功能

2细溅、抽象類的規(guī)則

  • Kotlin中的抽象類在頂層定義的時(shí)候只能使用public可見性修飾符修飾。
  • 抽象類中可以定義內(nèi)部抽象類儡嘶。
  • 只能繼承一個(gè)抽象類喇聊。
  • 若要實(shí)現(xiàn)抽象類的實(shí)例化,需要依靠子類采用向上轉(zhuǎn)型的方式處理蹦狂。
  • 抽象類可以繼承自一個(gè)繼承類誓篱,即抽象類可以作為子類。不過凯楔,抽象類建議不用open修飾符修飾窜骄,因?yàn)榭梢愿矊懗橄箢惖母割惖暮瘮?shù)。

例:

open class Base{
    open fun init(){}
}

abstract class Lanauage : Base(){
    val TAG = this.javaClass.simpleName  // 自身的屬性

    // 自身的函數(shù)
    fun test() : Unit{
        // exp
    }
    abstract var name : String           // 抽象屬性
    abstract override fun init()         // 覆寫父類的方法

    abstract class Name(){}              // 嵌套抽象類摆屯,可查看第二節(jié)中的嵌套類使用
}

fun main(args: Array<String>) {
    // 若要實(shí)現(xiàn)抽象類的實(shí)例化邻遏,需要依靠子類采用向上轉(zhuǎn)型的方式處理。
    val mLanauage : Lanauage = TestAbstarctB()
}

3虐骑、抽象類的實(shí)際應(yīng)用

  • Java的設(shè)計(jì)模式中准验,有一種設(shè)計(jì)模式叫模板設(shè)計(jì)模式,其定義為:
    • 定義一個(gè)操作中算法的骨架富弦,而將一些步驟延遲到子類中沟娱,模板方法使得子類可以不改變算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
    • 通俗點(diǎn)的理解就是 :完成一件事情腕柜,有固定的數(shù)個(gè)步驟,但是每個(gè)步驟根據(jù)對(duì)象的不同矫废,而實(shí)現(xiàn)細(xì)節(jié)不同盏缤;就可以在父類中定義一個(gè)完成該事情的總方法,按照完成事件需要的步驟去調(diào)用其每個(gè)步驟的實(shí)現(xiàn)方法蓖扑。每個(gè)步驟的具體實(shí)現(xiàn)唉铜,由子類完成。

KotlinJava是互通的律杠,說明Kotlin也是支持這種設(shè)計(jì)模式的潭流。

二竞惋、內(nèi)部類(嵌套類)

在實(shí)際開發(fā)中,用到內(nèi)部類的地方是很多的灰嫉。比如說:

  • 對(duì)于Android開發(fā)來說拆宛,列表適配器(adapter)中的ViewHolder類,就是一個(gè)內(nèi)部類讼撒。
  • 根據(jù)后臺(tái)開發(fā)人員提供的json字符串生成的對(duì)象中浑厚,也包含另外一個(gè)對(duì)象,這也是一個(gè)內(nèi)部類根盒。

1钳幅、嵌套類

上面提到的兩種情況,是在開發(fā)中最常見的炎滞。當(dāng)然敢艰,說到內(nèi)部類,就必須世道另一個(gè)概念嵌套類册赛,所謂的嵌套類:即指一個(gè)類可以嵌套在其他類中盖矫。

例:

class Other{           // 外部類
    val numOuther = 1

    class Nested {      // 嵌套類
        fun init(){
            println("執(zhí)行了init方法")
        }
    }
}

fun main(args: Array<String>) {
    Other.Nested().init()      // 調(diào)用格式為:外部類.嵌套類().嵌套類方法/屬性
}

輸出結(jié)果為:

執(zhí)行了init方法

注意:

  • 調(diào)用嵌套類的屬性或方法的格式為:外部類.嵌套類().嵌套類方法/屬性。在調(diào)用的時(shí)候嵌套類是需要實(shí)例化的击奶。
  • 嵌套類不能使用外部類的屬性和成員

2辈双、內(nèi)部類

在上面的例子中講解了嵌套類的使用,而內(nèi)部類和嵌套類還是有一定的區(qū)別的柜砾,而且內(nèi)部類是有特定的關(guān)鍵字去聲明的湃望。

2.1、關(guān)鍵字

聲明一個(gè)內(nèi)部類使用inner關(guān)鍵字痰驱。
聲明格式:inner class 類名(參數(shù)){}

例:

class Other{            // 外部類
    val numOther = 1

    inner class InnerClass{     // 嵌套內(nèi)部類
        val name = "InnerClass"
        fun init(){
            println("我是內(nèi)部類")
        }
    }
}

fun main(args: Array<String>) {
   Other().InnerClass().init()  // 調(diào)用格式為:外部類().內(nèi)部類().內(nèi)部類方法/屬性
}

注意:

  • 調(diào)用內(nèi)部類的屬性或方法的格式為:外部類().內(nèi)部類().內(nèi)部類方法/屬性证芭。在調(diào)用的時(shí)候嵌套類是需要實(shí)例化的
  • 內(nèi)部類不能使用外部類的屬性和成員

2.2担映、匿名內(nèi)部類

作為一名Android開發(fā)者废士,對(duì)匿名內(nèi)部類都不陌生,因?yàn)樵陂_發(fā)中蝇完,匿名內(nèi)部類隨處可見官硝。比如說ButtonOnClickListenerListView的單擊短蜕、長(zhǎng)按事件等都用到了匿名內(nèi)部類氢架。
一般的使用方式為定義一個(gè)接口,在接口中定義一個(gè)方法朋魔。

例:

class Other{

    lateinit private var listener : OnClickListener

    fun setOnClickListener(listener: OnClickListener){
        this.listener = listener
    }

    fun testListener(){
        listener.onItemClick("我是匿名內(nèi)部類的測(cè)試方法")
    }
}    

interface OnClickListener{
    fun onItemClick(str : String)
}

fun main(args: Array<String>){
    // 測(cè)試匿名內(nèi)部類
    val other = Other()
    other.setOnClickListener(object : OnClickListener{
        override fun onItemClick(str: String) {
            // todo
            println(str)
        }
    })
    other.testListener()
}

輸出結(jié)果為:

我是匿名內(nèi)部類的測(cè)試方法

遺留的問題

在上面實(shí)現(xiàn)的匿名內(nèi)部類是很常規(guī)的用法以及寫法岖研。在我們的實(shí)際開發(fā)當(dāng)中也是大家熟知的寫法。但是在我們實(shí)際開發(fā)當(dāng)中警检,會(huì)引入lambda語法糖孙援,讓我們的項(xiàng)目支持lambda語法害淤,簡(jiǎn)化代碼量。在這里我也是想把用lambda語法實(shí)現(xiàn)匿名內(nèi)部類實(shí)現(xiàn)的代碼貼出來拓售。

3窥摄、局部類

所謂局部類,這一點(diǎn)和Java是一致的邻辉。即定義在方法(函數(shù))中的類溪王。

例:

class Other{    // 外部類
    val numOther = 1

    fun partMethod(){
        var name : String = "partMethod"

        class Part{
            var numPart : Int = 2

            fun test(){
                name = "test"
                numPart = 5
                println("我是局部類中的方法")
            }
        }

        val part = Part()
        println("name = $name \t numPart = " + part.numPart + "\t numOther = numOther")
        part.test()
        println("name = $name \t numPart = " + part.numPart + "\t numOther = numOther")
    }
}

fun main(args: Array<String>) {
    // 測(cè)試局部類
    Other().partMethod()
}

輸出結(jié)果為:

name = partMethod    numPart = 2    numOther = 1
我是局部類中的方法
name = test      numPart = 5    numOther = 1

通過上面的實(shí)例:我們可以看出:

  • 局部類只能在定義該局部類的方法中使用。
  • 定義在實(shí)例方法中的局部類可以訪問外部類的所有變量和方法值骇。但不能修改
  • 局部類中的可以定義屬性莹菱、方法。并且可以修改局部方法中的變量吱瘩。

4道伟、靜態(tài)類

熟悉Java的朋友都知道Java的靜態(tài)類,或者說用static修飾符修飾的類使碾。但是在Kotlin中蜜徽,是不存在static關(guān)鍵字的。那么我們?cè)鯓尤?shí)現(xiàn)一個(gè)靜態(tài)類呢票摇?

關(guān)于靜態(tài)類的使用拘鞋,以及靜態(tài)類的語法。以及Koltin的單例模式實(shí)現(xiàn)矢门。由于篇幅原因我在這里就不展示了盆色。有興趣的朋友請(qǐng)參見kotlin中的object更像是語法糖。這篇文章是別的大牛詮釋靜態(tài)類以及單例實(shí)現(xiàn)很好的文章祟剔。后面我會(huì)出一篇詳細(xì)的文章為大家講解隔躲。

三、總結(jié)

在學(xué)完本篇博文中物延,你應(yīng)該掌握抽象類的作用宣旱,掌握其和普通類接口類叛薯、繼承類的區(qū)別所在浑吟,了解實(shí)現(xiàn)抽象類的意義,或者說在項(xiàng)目中為什么要用抽象類去編寫一個(gè)基類等案训。
對(duì)于嵌套類內(nèi)部類而言买置,知道這兩者的區(qū)別所在,和熟知他們?cè)陧?xiàng)目中用在什么地方就夠了强霎。對(duì)于靜態(tài)類來說,常用的實(shí)現(xiàn)都是用其去實(shí)現(xiàn)一個(gè)單例模式蓉冈。在Koltin的不像Java一樣實(shí)現(xiàn)很多的工具類城舞,因?yàn)?code>Kotlin中的擴(kuò)展功能很強(qiáng)大轩触。可以用擴(kuò)展去替換掉大部分的工具類家夺。本篇文章主要是展示object的用法而已脱柱,詳細(xì)的使用場(chǎng)景和用法會(huì)在后續(xù)的文章中為大家奉上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拉馋,一起剝皮案震驚了整個(gè)濱河市榨为,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌煌茴,老刑警劉巖随闺,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蔓腐,居然都是意外死亡矩乐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門回论,熙熙樓的掌柜王于貴愁眉苦臉地迎上來散罕,“玉大人,你說我怎么就攤上這事傀蓉∨肥” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵葬燎,是天一觀的道長(zhǎng)误甚。 經(jīng)常有香客問我,道長(zhǎng)萨蚕,這世上最難降的妖魔是什么靶草? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮岳遥,結(jié)果婚禮上奕翔,老公的妹妹穿的比我還像新娘。我一直安慰自己浩蓉,他們只是感情好派继,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捻艳,像睡著了一般驾窟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上认轨,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天绅络,我揣著相機(jī)與錄音,去河邊找鬼。 笑死恩急,一個(gè)胖子當(dāng)著我的面吹牛杉畜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衷恭,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼此叠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了随珠?” 一聲冷哼從身側(cè)響起灭袁,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窗看,沒想到半個(gè)月后茸歧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烤芦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年举娩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片构罗。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铜涉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遂唧,到底是詐尸還是另有隱情芙代,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布盖彭,位于F島的核電站纹烹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏召边。R本人自食惡果不足惜铺呵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望隧熙。 院中可真熱鬧片挂,春花似錦、人聲如沸贞盯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躏敢。三九已至闷愤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間件余,已是汗流浹背讥脐。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工遭居, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人攘烛。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓魏滚,卻偏偏與公主長(zhǎng)得像镀首,于是被迫代替她去往敵國和親坟漱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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