kotlin的特殊类(五)特殊类

本文深入探讨了Kotlin中的六种特殊类:嵌套类与内部类的区别、枚举类与密封类的特点、数据类的便利性和模板类的灵活性。通过具体示例,帮助读者更好地理解和运用这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、嵌套类
一个类可以在单独的代码文件中定义,也可以在另一个类内部定义,后一种情况叫做嵌套类,意即A类嵌套在B类之中。乍看过去,这个嵌套类的定义似乎与Java的嵌套类是一样的,但其实有所差别。Java的嵌套类允许访问外部类的成员,而Kotlin的嵌套类不允许访问外部类的成员。倘若Kotlin的嵌套类内部强行访问外部类的成员,则编译器会报错“Unresolved reference: ***”,意思是找不到这个东西。下面是Kotlin定义嵌套类的代码例子:

class Tree(var treeName:String) {
    //在类内部再定义一个类,这个新类称作嵌套类
    class Flower (var flowerName:String) {
        fun getName():String {
            return "这是一朵$flowerName"
            //普通的嵌套类不能访问外部类的成员如treeName
            //否则编译器报错“Unresolved reference: ***”
            //return "这是${treeName}上的一朵$flowerName"
        }
    }
}

2、内部类
既然Kotlin限制了嵌套类不能访问外部类的成员,那还有什么办法可以实现此功能呢?针对该问题,Kotlin另外增加了关键字inner表示内部,把inner加在嵌套类的class前面,于是嵌套类华丽丽转变为了内部类,这个内部类比起嵌套类的好处,便是能够访问外部类的成员。所以,Kotlin的内部类就相当于Java的嵌套类,而Kotlin的嵌套类则是加了访问限制的内部类。按照前面演示嵌套类的树木类Tree,也给它补充内部类的定义,代码如下所示:

class Tree(var treeName:String) {
    //在类内部再定义一个类,这个新类称作嵌套类
    class Flower (var flowerName:String) {
        fun getName():String {
            return "这是一朵$flowerName"
            //普通的嵌套类不能访问外部类的成员如treeName
            //否则编译器报错“Unresolved reference: ***”
            //return "这是${treeName}上的一朵$flowerName"
        }
    }
 
    //嵌套类加上了inner前缀,就成为了内部类
    inner class Fruit (var fruitName:String) {
        fun getName():String {
            //只有声明为内部类(添加了关键字inner),才能访问外部类的成员
            return "这是${treeName}长出来的$fruitName"
        }
    }
}

3、枚举类
Java有一种枚举类型,它采用关键字enum来表达,其内部定义了一系列名称,通过有意义的名字比0/1/2这些数字能更有效地表达语义。下面是个Java定义枚举类型的代码例子:

enum Season { SPRING,SUMMER,AUTUMN,WINTER }

4、密封类
前面演示外部代码判断枚举值的时候,when语句末尾例行公事加了else分支。可是枚举类SeasonType内部一共只有四个枚举变量,when语句有四个分支就行了,最后的else分支纯粹是多此一举。出现此种情况的缘故是,when语句不晓得SeasonType只有四种枚举值,因此以防万一必须要有else分支,除非编译器认为现有的几个分支已经足够。
为解决枚举值判断的多余分支问题,Kotlin提出了“密封类”的概念,密封类就像是一种更加严格的枚举类,它内部有且仅有自身的实例对象,所以是一个有限的自身实例集合。或者说,密封类采用了嵌套类的手段,它的嵌套类全部由自身派生而来,仿佛一个家谱明明白白列出来某人有长子、次子、三子、幺子。定义密封类时使用关键字sealed标记,具体的密封类定义代码如下所示:

sealed class SeasonSealed {
    //密封类内部的每个嵌套类都必须继承该类
    class Spring (var name:String) : SeasonSealed()
    class Summer (var name:String) : SeasonSealed()
    class Autumn (var name:String) : SeasonSealed()
    class Winter (var name:String) : SeasonSealed()
}

5、数据类
1、定义实体类的每个字段,以及对字段进行初始赋值的构造函数;
2、定义每个字段的get/set方法;
3、在判断两个数据对象是否相等时,通常要每个字段都比较一遍;
4、在复制数据对象时,如果想修改某几个字段的值,得再加对应数量的赋值语句;
5、在调试程序时,为了解数据对象里保存的字段值,得手工把每个字段值都打印出来;
6、模板类的应用如此广泛,Kotlin自然而然保留了它,并且写法与Java类似,一样在类名后面补充形如“”或者“<A, B>”的表达式,表示这里的类型待定,要等创建类实例时再确定具体的变量类型。待定的类型可以有一个,如ArrayList;可以有两个,如HashMap;也可以有三个或者更多,如AsyncTask。举个例子,森林里有一条小河,小河的长度可能以数字形式输入(包括Int、Long、Float、Double),也可能以字符串形式输入(String类型)。如果输入的是数字长度,则长度单位采取“m”;如果输入的是字符串长度,则长度单位采取“米”。按照以上需求编写名为River的模板类,具体的类定义代码如下:
//在类名后面添加“”,表示这是一个模板类

class River<T> (var name:String, var length:T) {
    fun getInfo():String {
        var unit:String = when (length) {
            is String -> "米"
            //Int、Long、Float、Double都是数字类型Number
            is Number -> "m"
            else -> ""
        }
        return "${name}的长度是$length$unit。"
    }
}

7、总结一下,本文介绍了Kotlin的六种特殊函数,首先嵌套类和内部类都定义在某个外部类的内部,区别在于能否访问外部类的成员;其次枚举类和密封类都提供了有序的枚举值集合,区别在于密封类的定义更加严格;再次是帮助开发者摆脱搬砖命运的数据类;最后是解决未定参数类型的模板类(也叫泛型类)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值