kotlin內部類、嵌套類


1.概念

​ 把類定義在其他類里面,定義在其他類內部的類即為嵌套類(或者寄生類),包含嵌套類的類稱為外部類(或者宿主類)。

​ 根據定義的方式不一樣,又分為內部類嵌套類局部嵌套類

​ 內部類、嵌套類相當於外部類成員之一,可以使用public|internal|protected|private來修飾。

2.內部類

​ 內部類相當於java沒有使用static修飾的內部類。使用inner關鍵字修飾。

(1)特點

  • 內部類成員可以直接訪問外部類的私有數據,因為內部類相當於外部類的成員之一;
  • 外部類不能訪問內部類的成員,如需訪問,需要通過創建內部類對象,通過對象訪問內部類成員。

(2)定義內部類

fun main(args: Array<String>) {
    OuterClass().getInnerFunction()
}

/**
 * 創建一個外部類
 */
class OuterClass {
    //外部類的屬性可被內部類使用
    private val outerParam = "外部類的私有屬性"

    /**
     * 外部類的私有方法可以被內部類調用
     */
    private fun outerTest() {
        println("外部類的私有方法")
    }

    /**
     * 通過該類創建內部類對象,調用內部類方法
     */
    fun getInnerFunction() {
//        innerTest()//這種外部類直接調用內部類成員的方式是編譯不通過的,因為此時根本不存在內部類的對象
        InnerClass().innerTest() //外部類想調用內部類,需定義一個內部類的對象,通過對象調用
    }

    /**
     * 創建一個內部類
     */
    inner class InnerClass {
        //內部類成員,在外部類通過內部類的對象獲取,但是內部類可以直接調用外部類成員
        fun innerTest() {
            println("內部類的方法方法,外部類屬性:$outerParam")//獲取外部類屬性
            outerTest()//調用外部類方法
        }
    }
}

(3)外部類-內部類交互原理

①為什么內部類可以調用外部類私有成員?

​ 在內部類對象中,保存了一個該內部類所寄生的外部類的對象的引用

​ 內部類在方法中訪問屬性順序:方法是否有該變量(如果沒有,下同)=》內部類是否有該屬性=》外部類是否有該屬性,如果都沒有,則編譯報錯。

②為什么外部類不能直接調用內部類成員?

​ 創建外部類對象時,內部類根本還不存在(如果沒有在外部類創建該內部類對象,(2)中的程序getInnerFunction()方法也是先創建了InnerClass對象才能調用InnerClass成員),因此也不存在直接使用該對象內部類的成員了。

3.嵌套類

​ 嵌套類相當於java的靜態內部類(static class),但是kotlin完全取消了static關鍵字,所以kotlin類中除去嵌套類,其余成員均為非靜態成員。

​ 內部類和嵌套類的使用考慮:優先考慮嵌套類。

(1)特點

  • 嵌套類不能訪問外部類的其他成員,只能訪問其他嵌套類(參考java靜態內部類,靜態成員不能訪問非靜態成員);
  • 跟內部類一樣,外部類不能直接調用嵌套類成員,如需調用,需創建嵌套類對象,通過對象調用嵌套類成員。

(2)定義嵌套類

fun main(args: Array<String>) {
    OuterClass().outerTest()
}

/**
 * 定義一個外部類
 */
class OuterClass {
    val outerParam = "外部類屬性"
    fun outerTest() {
//        nestedTest()//不可以直接調用嵌套類成員
        NestedClass().nestedTest()//可以通過創建嵌套類對象調用嵌套類成員
    }
    /**
     * 定義一個嵌套類(相當於java靜態內部類)
     */
    class NestedClass {
        fun nestedTest() {
//            println(outerParam)//此處是獲取不到外部類的屬性的
//            outerTest()//此處是調用不了外部類的方法的
            val nestClass2 = NestClass2()//可以訪問其他嵌套類
            println("嵌套類方法")
        }
    }

    /**
     * 其他嵌套類
     */
    class NestClass2
}

4.在外部類的外面使用內部類和嵌套類

(1)在外部類外部使用內部類(代碼接上)

fun main(args: Array<String>) {
    //在外部類的外部使用內部類
    val innerClass : OuterClass.InnerClass = OuterClass().InnerClass()
    innerClass.innerTest()
}

(2)在外部類外部使用嵌套類(代碼接上)

fun main(args: Array<String>) {
    //在外部類的外部使用外部類的嵌套類
    val nestedClass: OuterClass.NestedClass = OuterClass.NestedClass()
    nestedClass.nestedTest()
    val nestClass2 : OuterClass.NestClass2 = OuterClass.NestClass2()
}

5.局部嵌套類(用得少)

​ 把一個嵌套類放在方法或函數中定義,則這個嵌套類就是局部嵌套類。

(1)特點

  • 作用域:只在方法內有效;
  • 不能使用訪問權限修飾符(方法內變量均不允許);
  • 很雞肋

(2)定義局部嵌套類

fun main(args: Array<String>) {
    OuterClass().localInnerTest()
}

/**
 * 創建一個外部類
 */
class OuterClass {
    /**
     * 定義一個方法
     */
    fun localInnerTest() {
        /**
         * 方法內定義一個局部嵌套類,可以被繼承
         */
        open class LocalInnerClass {
            /**
             * 定義一個局部嵌套類的方法,可以被重寫
             */
            open fun localInnerTest() {
                println("LocalInnerClass")
            }
        }

        /**
         * 方法內定義另一個局部嵌套類,繼承於其他嵌套類
         */
        class SubLocalInnerClass : LocalInnerClass() {
            override fun localInnerTest() {
                println("SubLocalInnerClass")
            }
        }
        //只能在該方法內使用定義的局部嵌套類
        val localInnerClass = LocalInnerClass()
        localInnerClass.localInnerTest()
        val subLocalInnerClass = SubLocalInnerClass()
        subLocalInnerClass.localInnerTest()
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM