Kotlin系列五---数据类、密封类、内部类

本文介绍了Kotlin中的数据类、密封类和内部类的使用。数据类提供自动实现的equals(), hashCode()和toString()方法,以及copy()功能。密封类是一种特殊的抽象类,限制了其子类的数量,方便在when表达式中进行完全覆盖,避免使用else子句。内部类则是定义在另一个类内部的类,具有访问外部类成员的权限。" 113573073,8671452,渗透测试指南:客户端控件的安全审查,"['信息安全', '渗透测试', '网络安全', '应用安全', '客户端安全']

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

概述:kotlin的学习已经有一段时间了,每天都会花一点时间简单看看,看过之后过不了多久就会忘记,再一次证明只是是需要整理的,本片我们就来整理一下基本的几个类的使用,比较简单大致都是和kotlin网站上的东西差不多。

数据类
无论在java还是其它语言中,为了代码逻辑的清晰,我们总会创建一些只用于保存状态属性或数据的类,这些类称之为数据类,在kotlin中为了更加简单和规范的使用数据类,为数据类加上了自己的标志和修饰词data,并有了自己的规则,那我们创建一个简单的数据类:
data class DataClass(var  name : String) {

}
为了确保生成的代码的一致性和有意义的行为,数据类必须满足以下要求:
  • 主构造函数需要至少有一个参数;
  • 主构造函数的所有参数需要标记为 val 或 var;
  • 数据类不能是抽象、开放、密封或者内部的;
  • (在1.1之前)数据类只能实现接口。
创建数据类的对象并获取其属性:
var data = DataClass("NAME")
println(data)
println(data.name)
打印属性结果:
02-07 09:50:05.995 3256-3256/? I/System.out: DataClass(name=NAME)
02-07 09:50:05.995 3256-3256/? I/System.out: NAME
kotlin为数据类的创建定义了一直的标准,那限制的标准一定是为了实现部分共有的功能,在创建每个数据类时,编译器自动从主构造函数中声明的所有属性导出以下成员:
  • equals()/hashCode() 对;
  • toString() 格式是 "DataClass(name=NAME)";
  • componentN() 函数 按声明顺序对应于所有属性;
  • copy() 函数
toString()方法就和上面输出data一样,属性的获取在上面也使用过,我们打印一下equals和hasCode方法:
Log.e("=====", data.hashCode().toString())
Log.e("=====", data.equals(data.copy(name = "Change")).toString())
这里我们单独介绍一次啊copy的属性,copy从字面上是复制某个属性,不过kotlin的复制是允许用户修改属性的,或者叫不完全意义上的复制,产生的是一个属性不一定相同的不同对象,其内部的方法可以描述为:
fun copy(name: String = this.name) =DataClass  (name)    
现在我们复制data对象,改变其名字:
println(data.copy(name = "Change"))
println(data)
输出结果:
02-07 10:01:04.454 4444-4444/? I/System.out: DataClass(name=Change)
02-07 10:01:04.454 4444-4444/? I/System.out: DataClass(name=NAME)
解构声明
解构声明:顾名思义分解构造函数的每个参数,而创建对象,上文中创建data是:var data = ....,现在使用解构函数创建
var (name) = DataClass("A")//这里的name直接可以使用
Log.e("======",name)
02-07 10:08:17.444 5393-5393/? E/======: A

密封类
密封类用来表示受限的类继承结构:当一个值为有限集中的类型、而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。
要声明一个密封类,需要在类名前面添加 sealed 修饰符。虽然密封类也可以有子类,但是所有子类都必须在与密封类自身相同的文件中声明。(在 Kotlin 1.1 之前, 该规则更加严格:子类必须嵌套在密封类声明的内部)。
创建密封类和其子类:
sealed class Parent

data class ChildFirst(var name: String) : Parent()

data class ChildSecond(var name: String):Parent()

data class ChildThird(var name: String):Parent()
  • 一个密封类是自身抽象的,它不能直接实例化并可以有抽象(abstract)成员。
  • 密封类不允许有非-private 构造函数(其构造函数默认为 private)。
  • 请注意,扩展密封类子类的类(间接继承者)可以放在任何位置,而无需在同一个文件中。
  • 使用密封类的关键好处在于使用 when 表达式 的时候,如果能够验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。当然,这只有当你用 when 作为表达式(使用结果)而不是作为语句时才有用。
fun getName(parent: Parent) : String? = when (parent){
is ChildFirst -> parent.name
is ChildSecond -> parent.name
is ChildThird -> parent.name
}
内部类
kotlin中允许在一个类的内部嵌套一个类,不过此时的类不同于java中,两个类某种意义上的相互独立,内部的嵌套类无法使用外部的数据:
data class DataClass(var name: String) {
    
    class Data {
        fun print() {
            Log.e("===========", "DataClass.Data")
        }
    }

}

DataClass.Data().print()//02-07 10:23:40.106 6569-6569/? E/===========: DataClass.Data
此时的嵌套类虽然在一个累的内部,并不是嵌套类,因为kotlin中的内部类需要专有的修饰符:inner,现在我们修改上面的嵌套类:
var age: Int = 20

inner class Data {
     fun print() {
         Log.e("===========",age.toString())
     }
}
此时的调用方法也与之前的有所不同,要采用外部类的对象调用:
data.Data().print()
02-07 10:26:33.767 6909-6909/com.example.administrator.kotlinpractise E/===========: 20//输出外部类的数据
匿名内部类
使用对象表达式创建匿名内部类实例,我们对Rxjava的使用会比较多,我们就创建一个观察者的匿名对象:
Observable.just(1).subscribe(object : Observer<Int>{
    override fun onSubscribe(d: Disposable) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onNext(t: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onComplete() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onError(e: Throwable) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

})
使用object : T 创建T的匿名内部类,下面我们创建常用的设置点击事件的ClickListener:
air_view.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        println("Click")
    }

}
在kotlin中如果对象是函数式 Java 接口(即具有单个抽象方法的 Java 接口)的实例, 你可以使用带接口类型前缀的lambda表达式创建它:
air_view.setOnClickListener{  println("Click")}
对这三个类的创建和使用就简单介绍到这里,只要知道其使用的形式和代表的意义,在使用中根据需要灵活运用即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值