六种特殊的类

嵌套类一个类可以在单独的代码文件中定义,也可以在另一个类内部定义,后一种情况叫做嵌套类,意即A类嵌套在B类之中。乍看过去,这个嵌套类的定义似乎与Java的嵌套类是一样的,但其实有所差别。Java的嵌套类允许访问外部类的成员,而Kotlin的嵌套类不允许访问外部类的成员。倘若Kotlin的嵌套类内部强行访问外部类的成员,则编译器会报错“Unresolved reference: ***”,意思是找不到这个东西。
fun test(){ val flower = Tree.Flower(“荷花”) flower.getName() Tree(“向日葵”).Fruit(“apple”)}class Tree(var treeName:String){ class Flower(var flowerName:String){ fun getName():String{ return “荷花” } } inner class Fruit(var name:String){
}}调用嵌套类时,得在嵌套类的类名前面添加外部类的类名,相当于把这个嵌套类作为外部类的静态对象使用。
内部类既然Kotlin限制了嵌套类不能访问外部类的成员,那还有什么办法可以实现此功能呢?针对该问题,Kotlin另外增加了关键字inner表示内部,把inner加在嵌套类的class前面,于是嵌套类华丽丽转变为了内部类,这个内部类比起嵌套类的好处,便是能够访问外部类的成员。所以,Kotlin的内部类就相当于Java的嵌套类,而Kotlin的嵌套类则是加了访问限制的内部类。按照前面演示嵌套类的树木类Tree,也给它补充内部类的定义,class Tree(var treeName:String){ class Flower(var flowerName:String){ fun getName():String{ return “荷花” } } inner class Fruit(var name:String){
}}调用内部类时,要先实例化外部类,再通过外部类的实例调用内部类的构造函数,也就是把内部类作为外部类的一个成员对象来使用,这与成员属性、成员方法的调用方法类似。
枚举类Java有一种枚举类型,它采用关键字enum来表达,其内部定义了一系列名称,通过有意义的名字比0/1/2这些数字能更有效地表达语义开发者在代码中创建enum类型时,编译器会自动生成一个对应的类,并且该类继承自java.lang.Enum。因此,Kotlin拨乱反正,摒弃了“枚举类型”那种模糊不清的说法,转而采取“枚举类”这种正本清源的提法。具体到编码上,则将enum作为关键字class都得修饰符,使之名正言顺地成为一个类——枚举类。fun testEnum(){ val seasonName = Season.SPRING.seasonName}enum class Season(val seasonName:String){ SPRING(“春天”), SUMER(“夏天”), AUTUMN(“秋天”), WINTER(“冬天”)
}枚举类内部的枚举变量,除了可以直接拿来赋值之外,还可以调用枚举值的几个属性获得对应的信息
密封类前面演示外部代码判断枚举值的时候,when语句末尾例行公事加了else分支。可是枚举类SeasonType内部一共只有四个枚举变量,when语句有四个分支就行了,最后的else分支纯粹是多此一举。出现此种情况的缘故是,when语句不晓得SeasonType只有四种枚举值,因此以防万一必须要有else分支,除非编译器认为现有的几个分支已经足够。为解决枚举值判断的多余分支问题,Kotlin提出了“密封类”的概念,密封类就像是一种更加严格的枚举类,它内部有且仅有自身的实例对象,所以是一个有限的自身实例集合。或者说,密封类采用了嵌套类的手段,它的嵌套类全部由自身派生而来,仿佛一个家谱明明白白列出来某人有长子、次子、三子、幺子。定义密封类时使用关键字sealed标记,sealed class SeasonSealed{ class Spring(var name:String) class Sumer(var name:String) class Autum(var name:String) class Winter(var name:String)}
数据类在Android开发中,免不了经常定义一些存放数据的实体类,比如用户信息、商品信息等等,每逢定义实体类之时,开发者基本要手工完成以下编码工作:1、定义实体类的每个字段,以及对字段进行初始赋值的构造函数;2、定义每个字段的get/set方法;3、在判断两个数据对象是否相等时,通常要每个字段都比较一遍;4、在复制数据对象时,如果想修改某几个字段的值,得再加对应数量的赋值语句;5、在调试程序时,为了解数据对象里保存的字段值,得手工把每个字段值都打印出来;如此折腾一番,仅仅是定义一个实体类,开发者就必须完成这些繁琐的任务。然而这些任务其实毫无技术含量可言,如果每天都在周而复始地敲实体类的相关编码,毫无疑问跟工地上的搬砖民工差不多,活生生把程序员弄成一个拼时间拼体力的职业。有鉴于此,Kotlin再次不负众望推出了名为“数据类”的大兵器,直接戳中程序员事多、腰酸、睡眠少的痛点,极大程度上将程序员从无涯苦海中拯救出来。数据类说神秘也不神秘,它的类定义代码极其简单,只要开发者在class前面增加关键字“data”,并声明入参完整的构造函数,即可无缝实现以下功能:1、自动声明与构造入参同名的属性字段;2、自动实现每个属性字段的get/set方法;3、自动提供equals方法,用于比较两个数据对象是否相等;4、自动提供copy方法,允许完整复制某个数据对象,也可在复制后单独修改某几个字段的值;5、自动提供toString方法,用于打印数据对象中保存的所有字段值;功能如此强大的数据类,犹如步枪界的AK47,持有该款自动步枪的战士无疑战斗力倍增。data class DataClass(var name: String){ constructor( age: Int):this(“java”)}
模板类写法与Java类似,一样在类名后面补充形如“”或者“<A, B>”的表达式,表示这里的类型待定,要等创建类实例时再确定具体的变量类型。待定的类型可以有一个,如ArrayList;可以有两个,如HashMap;也可以有三个或者更多,如AsyncTask。举个例子,森林里有一条小河,小河的长度可能以数字形式输入(包括Int、Long、Float、Double),也可能以字符串形式输入(String类型)。如果输入的是数字长度,则长度单位采取“m”;如果输入的是字符串长度,则长度单位采取“米”。class River(var name:String,var length:T){ fun getInfo():String{ var unit:String = when(length){ is String -> “米” is Number -> “m” else -> “” } return “ n a m e 长 度 是 {name}长度是 namelength$unit” }}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值