当前位置:网站首页>Kotlin特殊类
Kotlin特殊类
2022-07-30 22:57:00 【尘心平】
数据类Data Class
数据类即只用来保存数据的类
数据类会根据主构造函数的定义的属性自动推导出equals、hashcode、toString、componentN以及copy函数
数据类的声明
数据类采用 data class 声明,必须有主构造函数且采用定义属性的方式,主构造函数至少定义一个属性
数据类不可继承open、不可内部inner、不可密封sealed、不可抽象abstract
data class CarBean(var name:String,var sex:String,var age:Int){} fun main(args:Array<String>){ //CarBean 默认实现toString val bean1=CarBean("Peter","Male",17) val bean2=CarBean("Alice","Female",18) println(bean1)//CarBean(name=Peter, sex=Male, age=17) println(bean2)//CarBean(name=Alice, sex=Female, age=18) //默认实现equals 比较主构造参数内的所有定义属性 println(bean1==CarBean("Peter","Male",17))//true //默认实现hashcode println(bean1.hashCode())//1061749360 println(CarBean("Peter","Male",17).hashCode())//1061749360 //默认实现copy val bean3=bean1.copy(age=18)//更改年龄,其他相同 println(bean3)//CarBean(name=Peter, sex=Male, age=18) //默认实现componentN val (name,sex,age)=bean3 println("$name $sex $age")//Peter Male 18 }
注意事项
1.如果数据类显式实现了toString或者equals或者hashcode函数,则数据来使用这些方法时,使用显式实现
2.数据类不能提供copy和componentN函数的显式实现
特点
1.使用自动生成的copy函数可以进行已有对象的拷贝,且()内可以使用关键字传参指定与已有对象不同的属性
语法:val/var 变量=对象.copy(属性=值),默认是完全拷贝
2.使用自动生成的componentN函数可以对数据类对象进行解构
语法:val/var (变量 数目与属性数形态)=对象
在类体中声明的属性
因为数据类的toString、equals、hashcode、copy、componentN函数均是根据主构造函数内定义的属性生成的,并不包括类体中属性初始化器声明的属性,所以调用这些方法时是不针对类体中的属性的,如果需要针对则可用重写toString、equals、hashcode函数‘
data class CarBean(var name:String,var sex:String){ var age:Int=0 } fun main(args:Array<String>){ val bean1=CarBean("Peter","Male") val bean2=CarBean("Alice","Female") println(bean1)//CarBean(name=Peter, sex=Male) println(bean2)//CarBean(name=Alice, sex=Female) bean1.age=18 println(bean1==CarBean("Peter","Male"))//True println(bean1.hashCode().toString()+" "+CarBean("Peter","Male").hashCode()) //-1905412671 -1905412671 //println(bean1.copy(age=18)) //Cannot find a parameter with this name: age println(bean1.copy(name="Job")) //只能拷贝主构造函数中有的属性 CarBean(name=Job, sex=Male) val (name,sex)=bean1 //也只能解析主构造函数中的属性 }
当类中重写了toString、hashcode、equals方法时,则将会对除copy和解析之外的使用产生影响
data class CarBean(var name:String,var sex:String){ var age:Int=0 override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as CarBean if (name != other.name) return false if (sex != other.sex) return false if (age != other.age) return false return true } override fun hashCode(): Int { var result = name.hashCode() result = 31 * result + sex.hashCode() result = 31 * result + age return result } override fun toString(): String { return "CarBean(name='$name', sex='$sex', age=$age)" } } fun main(args:Array<String>){ val bean1=CarBean("Peter","Male") val bean2=CarBean("Alice","Female") println(bean1)//CarBean(name='Peter', sex='Male', age=0) println(bean2)//CarBean(name='Alice', sex='Female', age=0) bean1.age=18 println(bean1==CarBean("Peter","Male"))//False println(bean1.hashCode().toString()+" "+CarBean("Peter","Male").hashCode()) //1061749361 1061749343 //println(bean1.copy(age=18)) //Cannot find a parameter with this name: age println(bean1.copy(name="Job")) //只能拷贝主构造函数中有的属性 CarBean(name=Job, sex=Male, age=0) val (name,sex)=bean1 //也只能解析主构造函数中的属性 }
密封类
什么是密封类
密封类是用来表示受限的类继承结构:对象只能表示有限的几种类型
密封类和枚举类类似,枚举类是表示受限对象的类,类只能有这几个实例对象,一个是针对的变量的类型,一个是针对变量的值
密封类的声明使用
声明一个密封类,需要在类名前面添加
sealed
修饰符密封类的子类必须与密封类在同一文件中,而密封类的子类的子类无此限制
密封类不允许有非private的构造函数,所有密封类不能直接实例化
密封类的子类需有状态,且需要重写equals函数
一般使用是在when表达式中,验证密封类对象的类型
sealed class A{} data class B(val name:String):A(){} data class C(val sex:String):A(){} object D:A() fun main(args:Array<String>){ val a:(x:A)->Unit={ when(it){ D->{ println("$it is D") } is B->{ println("$it is B") } is C->{ println("$it is C") } } } //包含了所有的情况,when内不需要else }
嵌套类
类简单的嵌套在其他类中相当于C++中的静态内部类,不能使用外部类的成员方法
类可用和接口互相嵌套,接口也可以嵌套接口
类内嵌套接口,是静态嵌套的(接口不能使用inner关键字)
类内嵌套类,一般是静态嵌套,如果有inner关键字则是类的成员
接口内嵌套类或者接口均是静态嵌套(接口内也不能用inner关键字)
class A(val nameA:String){ fun printA(){ print("$nameA ") println("This is method of A ,which is named printA") } //类内嵌套类 class B(val nameB:String){ //printA() Expecting member declaration fun printB(){ //name Unresolved reference: name print("$nameB ") println("This is method of B ,which is named printB") } } //嵌套类相当于C++静态内部类,不能使用外部类的成员 //类内嵌套接口 fun interface C{ fun write() } } interface B{ class A{ fun work(){ } } //接口内嵌套类是静态嵌套的,类不是默认抽象的 interface C{ fun work() } //接口内嵌套接口也是静态嵌套的,继承B,并不需要实现C } fun main(args:Array<String>){ val a=A("Alice") val b=A.B("Bob") //可以直接使用外部类名访问嵌套类 a.printA() //Alice This is method of A ,which is named printA b.printB() //Bob This is method of B ,which is named printB val c=A.C{ println("This is A.C interface achievement") } c.write()// This is A.C interface achievement }
内部类
内部类是特殊的嵌套类,即在嵌套类声明定义前加inner关键字,此时的嵌套类叫做内部类
内部类是外部类的一个成员,需要凭借对象才能访问,内部类也可以访问外部类的其他成员
class A(val nameA:String){ fun printA(){ print("$nameA ") println("This is method of A ,which is named printA") } //类内嵌套类 inner class B(val nameB:String){ fun printB(){ print("$nameB $nameA") println("This is method of B ,which is named printB") printA() } //内部类可以使用外部类的所有成员(private public internal protected) } } fun main(args:Array<String>){ val a=A("Alice") //val b=A.B("Bob") //不能直接用外部类名访问内部类 val b=a.B("Bob") //需要通过外部类的对象访问内部类 a.printA() //Alice This is method of A ,which is named printA b.printB() //Bob AliceThis is method of B ,which is named printB //Alice This is method of A ,which is named printA }
匿名内部类
可用使用 object:类的对象{ } 来创建匿名内部类
当对象是函数式接口时,可用直接使用 接口名{函数体} 来创建
window.addWindowFocusListener(object :WindowFocusListener{ override fun windowGainedFocus(e: WindowEvent?) { TODO("Not yet implemented") } override fun windowLostFocus(e: WindowEvent?) { TODO("Not yet implemented") } })
这个在后续Android开发中添加按钮比较常用
枚举类
枚举类是对对象的值有限制,对象只能是枚举常量
边栏推荐
- 通过社交媒体建立个人IP的 5 种行之有效的策略
- 482-静态库、动态库的制作、使用及区别
- 正则表达式语法及使用
- 2022.7.30
- Go1.18升级功能 - 泛型 从零开始Go语言
- Introducing the visualization tool Netron
- 电脑快捷方式图标变白解决方案
- "Code execution cannot continue because MSVCP140.dll was not found, reinstalling the program may resolve the problem, etc." Solutions
- MySQL的一个问题
- vulnhub靶机AI-Web-1.0渗透笔记
猜你喜欢
【MySQL】MySQL中对数据库及表的相关操作
Apache Doris系列之:深入认识实时分析型数据库Apache Doris
Rust编译报错:error: linker `cc` not found
2021GDCPC广东省大学生程序设计竞赛 H.History
ThinkPHP高仿蓝奏云网盘系统源码/对接易支付系统程序
WSL2设置默认启动用户(debian)
ML之shap:基于FIFA 2018 Statistics(2018年俄罗斯世界杯足球赛)球队比赛之星分类预测数据集利用RF随机森林+计算SHAP值单样本力图/依赖关系贡献图可视化实现可解释性之攻略
PhpMetrics 使用
宁波中宁典当转让29.5%股权为283.38万元,2021年所有者权益为968.75万元
通过对抗性知识蒸馏压缩深度图神经网络
随机推荐
【Untitled】
Go1.18升级功能 - 模糊测试Fuzz 从零开始Go语言
2022.7.30
[MySQL] DQL related operations
Py's pdpbox: a detailed introduction to pdpbox, installation, and case application
Debezium error series 20: task failed to create new topic. Ensure that the task is authorized to create topics
【Untitled】
2021GDCPC Guangdong University Student Programming Competition B.Byfibonacci
解决一个Mysql的utf8编码导致的问题
PS基础学习(一)
2021GDCPC广东省大学生程序设计竞赛 B.Byfibonacci
成功解决ModuleNotFoundError: No module named ‘Image‘
Computer shortcut icon whitening solution
阿里云视频点播+项目实战
el-upload添加请求头
Rust编译报错:error: linker `cc` not found
【微信小程序】小程序突破小程序二维码数量限制
MySQL进阶sql性能分析
正则表达式语法及使用
【无标题】