文章目录

  • 一、数据类
    • 1.1、使用数据类
    • 1.2、对象复制
    • 1.3、数据类成员的解构
  • 二、封闭类

一、数据类

  数据类是 Kotlin 的一个语法糖。 Kotlin 编译器会自动为数据类生成一些成员函数,以提高开发效率

1.1、使用数据类

  如果在程序中使用数据库,或映射 JSON 数据,很可能会将查询结果集或 JSON 格式的数 据映射成 为对象,或将对象映射成为数据集或 JSON 格式的数据。无论是哪一种,我们总是需 要一个类来表示数据。例如,要表示用户的数据,需要建立一个 User 类,并通过构造器传入 两个参数值: name和 age。


class User(name : String,age : Int)
{var name : String  = namevar age : Int  = age
}

  在User类中,主构造器有两个参数: name和age,在类中还定义了两个 属性: name和 age,并用主构造器的两个参数分别初始化了两个成员属性。
  对于表示数据的类来说,除了要保存数据外,还要进行一些操作, 如输出对象的值,比较对象是否 相等 。 Kotlin 代码前者会调用对象的 toString 函数,后者会调用对象的 equals 函数。

    /*** 输出user1 和user2 时,调用了这两个对象的toString函数,* 而toString函数默认会调用hashcode函数输出当前对象的hashcode,* 并在前面加上"类名@",就像User@*/var user1 : User = User("mike",21)var user2 : User = User("mike",21)println(user1)println(user2)/*** 对象的 equals方法默认比较了对象之间的 hashcode,如果相同,就是一个对象,它们也就 相等了 。* 不过,在实际应用中,需要 toString 函数输出对象属性值,* 而 equals 函数通过属性值 是否相等进行比较。* 只有所有的属性值都相等,两个对象才会判定相等。*/println(user1.equals(user2))

  为了使用 toString 函数输出 name 和 age 属性值,使用 equals 函数比较两个 User对象是否 相等,需要在 User类中重写这两个函数,代码如下:


class User(name : String,age : Int)
{var name : String  = namevar age : Int  = ageoverride fun toString(): String {return "User (name = ${name},age = ${age})"}override fun equals(other: Any?): Boolean {// 判断other是否为User对象, 如果不是User对象,直接返回falseif(other is User){//kt会自动转换数据类型, 根据is来判断,other现在已经是User对象了if(name == other.name && age == other.age){return true}}else{return false}return false}}

   User 类尽管可 以完全满足我们的要求,但如果每个表示数据 的类都要重写 toString和 equals方法,而且都要加属性,岂不是很麻烦,为了让开发效率更进 一步提升 , Kotlin 加入了数据类。所谓数据类,其实就是只定义必要的部分,其 余的部分 ,可以自动推导。
   从 User类的代码可以看出,只有 name 和 age 是必要的,其余的都可以自动推导,因此, 只需要在 User类中指定 name 和 age 即可。如何指定 name 和 age 呢?数据类规定,属性要通 过主构造器指定,而且数据类要在 class关键宇前面加 data。因此,如果前面的 User类用数据 类的写法 ,就变成了下面的样子。

data class User(val name : String,var age : Int)


User数据类中并没有类的实现体,实际上,数据类和普通类完全一样, 也可以拥有类的实现体, 数据类和普通类最大不同,就是数据类可以根据主构造器的参数自动生成相关的代码,因此, 如果一个 Kotlin类,同时兼有普通类,以及存储和管理数据的功能,建议直接使用数据类。

open class MyClass
{}
data class User(val name : String,var age : Int):MyClass()
{fun process(){println("process")}
}

编写 一个数据类需要注意的事项如下 。

  • 主构造器至少要有 一个参数。
  • 主构造器的所有参数必须标记为 val或 var。
  • 数据类不能是抽象类 、 open 类、封闭( sealed)类或内部 (inner)类。
      由于数据类要求主构造器必须至少有一个参数 , 因此在数据类中,不可能存在没有参数的 主构造器, 要想让数据类拥有一个没有参数的构造器,有如下两种方法。
  • 为主构造器每一个参数都加上默认值 。
  • 添加一个没有参数的次构造器,并在调用主构造器时指定主构造器参数的默认值。
       其实这两种方法的效果是一样的,就是主构造器的每一个参数必须要有一个默认值才能实现没有参数的构造器。

为主构造器的每一个参数添加一个默认值

data class User(val name : String = "Bill",var age : Int = 20)

添加一个次构造器

data class User(val name : String = "Bill",var age : Int = 20):MyClass()
{//添加一个构造器  次构造器constructor():this("Bill",20){}fun process(){println("process")}
}
1.2、对象复制

  在实际应用中 , 经常需要复制一个对象,然后修改它的一部分属性, 这就需要数据类提供 一种机制可以复制对象。在前面讲过, Kotlin编译器会为数据类 自动生成一些代码 (bytecode), 这些代码不仅包括 toS仕ing和 equals,还包括一个 copy 函数,该函数的作用就是复制数据类的实例。

  copy 函数的代码 ,核心代码就是下面的样子 。 很明显,在 copy 函数中,就是创建了一个当前数据类的实例, 并传入了 name和 age属性

fun copy(name: String = this.name,age : Int = this.age) = User(name,age)

使用数据类可直接调用copy()函数

1.3、数据类成员的解构

  现在先来解释一下什么叫数据类成员的解构 ,这里的关键是解构 ,也就是解除结构 。在数 据类中,用属性表示数据, 这些属性属于同一个数据类。要想使用这些属性,必须要首先引用 数据类对象。这里的解构就是指将这些数据对象中 的属性提取出来,分别赋给单个的变量 ,这 样就可以单独使用它们了

val jane = MyUser(name = "Jane",age = 20)//将MyUser.name  MyUser.age 分别赋予name和age变量val (name,age) = janeprintln("$name , $age year of age")

二、封闭类

  封闭类也是 Kotlin 的一个语法糖。可以把它理解为枚举的扩展。一个封闭类,前面用 sealed关键字标识。可以有任意多个子类或对象。封 闭类的值只能是这些子类或对象 。使用封闭类的 好处主要是 when 表达式,不需要再使用 else 形式了。下面给出一个例子。

sealed class Exprdata class Const(val number : Double) : Expr()data class Sum(val param1 : Expr,val param2 : Expr) : Exprobject NotANumber : Expr()fun eval (expr: Expr) : Double = when(expr)
{is Const -> expr.numberis Sum -> eval(expr.param1) + eval(expr.param2)NotANumber -> Double.NaN//在这里不要求使用else子句匹配其他情况
}

  在这段代码中 , Expr 是一个封闭类,该类有两个数据类( Const 和 Sum)和一个对象 CNotANumber)。下面的函数判断 Expr 类型参数 的种类,这里面只有 3 个种类: Const、 Sum 和 NotANumber

Kt学习笔记(九)数据类、封闭类相关推荐

  1. Kotlin学习笔记12——数据类和密封类

    Kotlin学习笔记12--数据类和密封类 前言 数据类 在类体中声明的属性 复制 componentN 解构声明 密封类 尾巴 前言 上一篇,我们学习了Kotlin中的拓展,今天继续来学习Kotli ...

  2. PyTorch学习笔记(六)——Sequential类、参数管理与GPU

    系列文章\text{\bf 系列文章}系列文章 PyTorch学习笔记(一)--Tensor的基础语法 PyTorch学习笔记(二)--自动微分 PyTorch学习笔记(三)--Dataset和Dat ...

  3. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

  4. Kotlin 学习笔记(七)—— Kotlin类与对象之属性与字段

    Kotlin 学习笔记(七)-- Kotlin类与对象之属性与字段 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- ...

  5. at24c16如何划分出多个读写区_AVR学习笔记九、基于AT24C16的数据存储实验

    Ema{@AVR 学习笔记九.基于 AT24C16 的数据存储实验 ------- 基于 LT_Mini_M16 9.1 用 I/O 口模拟 I2C 总线实现 AT24C16 的读写 9.1.1 .实 ...

  6. 吴恩达《机器学习》学习笔记九——神经网络相关(1)

    吴恩达<机器学习>学习笔记九--神经网络相关(1) 一. 非线性假设的问题 二. 神经网络相关知识 1.神经网络的大致历史 2.神经网络的表示 3.前向传播:向量化表示 三. 例子与直觉理 ...

  7. 学习笔记之数据可视化(二)—— 页面布局(下)

    续上一章 2.7 地图区域(.map) 2.7.1 实现步骤: 2.8 用户统计模块 2.8.1 布局: 2.8.2 柱状图 2.9 订单模块 2.9.1 订单区域布局 2.9.2 订单区域(orde ...

  8. 学习笔记之数据可视化(二)——页面布局(上)

    ~续上一章 2. 项目页面布局 2.1 基础布局 2.1.1 PC端屏幕宽度适配设置 2.1.2 主体容器viewport背景图片 2.1.3 HTML结构 2.1.4 css样式代码 2.2 边框图 ...

  9. JPA学习笔记---JPA数据的操作:增加,删除,修改,获取,使用JPQL进行查询

    JPA学习笔记---JPA数据的操作:增加,删除,修改,获取,使用JPOL进行查询 创梦技术交流平台:资源下载,技术交流,网络赚钱: 交流qq群:1群:248318056 2群:251572072 技 ...

最新文章

  1. QIIME 2教程. 10数据导出ExportingData(2021.2)
  2. apche 虚拟主机设置
  3. .NET常见线程简介
  4. Kotlin实战指南七:单例模式
  5. 异常php有必要吗,关于php异常的问题,到底有什么好处?
  6. 用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发
  7. 如何用 IDEA 提升十倍开发效率?
  8. SQLite使用报告
  9. 前端新手入门必读!前端开发线路图分享
  10. smarty php5.5,smarty如何完美兼容php5.5和preg_replace_callback如何替换preg_r
  11. 变量作用域、声明提前、作用域链
  12. Java高效开发12个精品库
  13. 首席架构师白鳝:运维的进阶与哲学之道
  14. 从一个月2500没人要到大厂技术主管的编程之路|我的十年
  15. 常见的数据结构及其特征
  16. myEclipse10破解及过期处理
  17. 解决“该jenkins实例似乎已离线”
  18. Map集合通过value获取key的几种方式
  19. STM32机器人控制开发教程No.3 使用遥控控制电机/舵机(基于HAL库)
  20. 1012:计算多项式的值

热门文章

  1. 从零实现Vue的组件库(十二)- Table 实现
  2. BootStrap4工具类之阴影效果
  3. 基于多传感器的AUV控制系统
  4. azure 配置vpn_ASP.NET和Azure中配置中的私有配置数据和连接字符串的最佳做法
  5. 十二 iOS之 折叠图片
  6. golang_iota
  7. 牛客算法周周练16全题解
  8. 第2章 多维数据结构与运算答案
  9. 服务器系统开机提示0xc000007b,重装系统出现0xc000007b无法正常启动怎么解决
  10. K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法