嵌套类和内部类(inner class)

547 阅读3分钟

在实际开发中,用到内部类的地方是很多的。比如说:

  • 对于Android开发来说,列表适配器(adapter)中的ViewHolder类,就是一个内部类。
  • 根据后台开发人员提供的json字符串生成的对象中,也包含另外一个对象,这也是一个内部类。

一、嵌套类

上面提到的两种情况,是在开发中最常见的。当然,说到内部类,就必须说道另一个概念嵌套类,所谓的嵌套类:即指一个类可以嵌套在其他类中。

例:

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

    class Nested {      // 嵌套类
        fun init(){
            println("执行了init方法")
        }
    }
}

fun main(args: Array<String>) {
    Other.Nested().init()      // 调用格式为:外部类.嵌套类().嵌套类方法/属性
}

输出结果为:

执行了init方法

注意:

  • 调用嵌套类的属性或方法的格式为:外部类.嵌套类().嵌套类方法/属性。在调用的时候嵌套类是需要实例化的
  • 嵌套类不能使用外部类的属性和成员。

二、内部类

在上面的例子中讲解了嵌套类的使用,而内部类和嵌套类还是有一定的区别的,而且内部类是有特定的关键字去声明的。

2.1、关键字

声明一个内部类使用inner关键字。 声明格式:inner class 类名(参数){}

例:

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

    inner class InnerClass{     // 嵌套内部类
        val name = "InnerClass"
        fun init(){
            println("我是内部类")
        }
    }
}

fun main(args: Array<String>) {
   Other().InnerClass().init()  // 调用格式为:外部类().内部类().内部类方法/属性
}

注意:

  • 调用内部类的属性或方法的格式为:外部类().内部类().内部类方法/属性。在调用的时候内部类是需要实例化的
  • 内部类能使用外部类的属性和成员。

2.2、匿名内部类

作为一名Android开发者,对匿名内部类都不陌生,因为在开发中,匿名内部类随处可见。比如说ButtonOnClickListenerListView的单击、长按事件等都用到了匿名内部类。 一般的使用方式为定义一个接口,在接口中定义一个方法。

例:

class Other{

    lateinit private var listener : OnClickListener

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

    fun testListener(){
        listener.onItemClick("我是匿名内部类的测试方法")
    }
}    

interface OnClickListener{
    fun onItemClick(str : String)
}

fun main(args: Array<String>){
    // 测试匿名内部类
    val other = Other()
    other.setOnClickListener(object : OnClickListener{
        override fun onItemClick(str: String) {
            // todo
            println(str)
        }
    })
    other.testListener()
}

输出结果为:

我是匿名内部类的测试方法

遗留的问题

在上面实现的匿名内部类是很常规的用法以及写法。在我们的实际开发当中也是大家熟知的写法。但是在我们实际开发当中,会引入lambda语法糖,让我们的项目支持lambda语法,简化代码量。在这里我也是想把用**lambda语法实现匿名内部类实现的代码贴出来**。

三、局部类

所谓局部类,这一点和Java是一致的。即定义在方法(函数)中的类。

例:

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>) {
    // 测试局部类
    Other().partMethod()
}

输出结果为:

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

通过上面的实例:我们可以看出:

  • 局部类只能在定义该局部类的方法中使用。
  • 定义在实例方法中的局部类可以访问外部类的所有变量和方法。但不能修改
  • 局部类中的可以定义属性、方法。并且可以修改局部方法中的变量。