转向Kotlin——数据类和封闭类

数据类和封闭类是Kotlin中的两种特殊的类,今天一起了解一下。

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

数据类的使用

无论是Java服务器开发还是Android开发,实体类自然是特别熟悉,它就是讲json格式转化为一个只包含数据和基本操作方法的实体类,以方便网络存取和数据库存取。

我们总是需要一个类来表示数据,例如要表示一个用户的数据,我们会创建一个User类,并通过构造器传入两个属性:

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

我们定义实体类,除了要保存数据之外,还需要输出对象的值,比较对象等操作,前者会用到toString函数,后者会用到equals函数,如下:

var user1 = User("js", 20)
var user2 = User("lx", 12)
println(user1)
println(user2)
println(user1.equals(user2))

输出结果是:

User@3764951d
User@4b1210ee
false

从结果可以看出,输出User的两个对象时,调用了这两个对象的toString方法,但toString函数默认会调用hashcode函数,输出当前对象的hashcode,并在前面加上 类名@

对象的equals方法默认也是比较了两个对象的hashcode,两个对象hashcode不同,自然返回false。

有时我们的业务需求是这样的:打印对象,即按规则打印对象的所有属性,两个对象的所有属性值相同,则返回两个对象相等,于是乎我们需要重写toString函数和equals函数,相信大家都会写,这里就不再累赘了。

尽管前面写的User类实现了我们的需求,但会不会也太麻烦了,每个类都需要重写toString和equals等方法。为了提高开发效率,Kotlin加入了我们马上要介绍的数据类。

所谓数据类,就是只定义必要的部分,其余部分可以自动生成。

从上面的类可以看出,只有name和age是必须的,其余的都是可以自动推导的。数据类规定:属性要通过主构造器指定,而且还要在class关键字之前加data。我们再写一个数据类,如下:

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

可以看出,原本十几行几十行的代码,现在一行就搞定了,其余的Kotlin编译器会自动生成。

数据类也和普通类一样,也可以继承其他类,有一些其他的成员函数等。

编写一个数据类需要注意:

  • 主构造器至少要有一个参数;
  • 主构造器的参数要用var或val修饰;
  • 数据类不能是抽象类、open类、封闭类或者内部类。

由于主构造器中必须至少要有一个参数,所以在数据类中,不可能存在无参的主构造器,要想让数据类用友一个无参的构造器,有以下两种方法:

  1. 为主构造器的每一个参数都加上默认值;
  2. 添加一个没有参数的次构造器,并调用主构造器同时制定各参数。
data class MPerson(var name: String = "js", var age: Int = 20)
data class NPerson(var name: String, var age: Int) {
    // 次构造器,this调用猪狗早起,并指定参数
    constructor() : this("js", 20)
}

对象的复制

在开发中,我们经常需要复制一个对象,然后修改它的一部分属性,这就需要一个复制机制,Kotlin除了为数据类自动生成toString方法和equals方法,还默认生成了一个copy方法,它的作用就是复制数据类的实例。代码如下:

var person = Person("wj", 20)
var mCopyPerson1 = person.copy()
var mCopyPerson2 = person.copy(name = "js")

数据类成员的解构

所谓解构,就是解除解构,指的是将数据对象中的属性提取出来,分别赋给单个变量。

Kotlin编译器会自动为数据类生成组件函数(以后会说到),隐藏,可以直接将数据类成员解构:

var js = Person("Js", 20)
// 将js.name和js.age分别赋给name和age变量
var (name, age) = js
println("$name, is $age years old")

封闭类

封闭类可以看作是枚举的扩展。一个封闭类,前面用sealed关键字标识。可以有人以多个子类和对象。封闭类的值只能是这些子类和对象。

使用封闭类的好处是when表达式,不需要再使用else形式了。看个例子:

sealed class Expr
data class Const(var count: Int) : Expr()
data class Sun(var e1: Expr, var e2: Expr) : Expr()
fun evel(expr: Expr): Int = when (expr) {
    is Const -> expr.count
    is Sun -> evel(expr.e1) + evel(expr.e2)
}

总结

在Kotlin中提供了一些特殊的类,其中数据类和封闭类就是其中的两个。尽管这些特殊的类并不是必须的,但有些时候使用它们会给我们的开发带来很大的方便,尤其是数据类。

原文发布于微信公众号 - Android机动车(JsAndroidClub)

原文发表时间:2018-05-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Danny的专栏

【J2SE快速进阶】——IO流的四个基本抽象类InputStream、OutputStream、Reader、Writer

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

1032
来自专栏一个会写诗的程序员的博客

《一切皆是映射:代码的本质》Java 动态读取源代码,并编译 & 加载执行

动态的执行一段简单代码,采用生成java文件,调用javac编译,反射执行的方式。

2303
来自专栏Laoqi's Linux运维专列

python3–练习题

6085
来自专栏云霄雨霁

Java--运行期类型鉴定(RTTI)

1655
来自专栏从零开始学自动化测试

python笔记22-literal_eval函数处理返回json中的单双引号

在做接口测试的时候,最常见的接口返回数据就是json类型,json类型数据实际上就是字串,通常标准的json格式是可以转化成python里面的对应的数据类型的 ...

1761
来自专栏ShaoYL

深刻理解----修饰变量----关键字

35311
来自专栏程序员同行者

Python 元组知识点

1683
来自专栏LuckQI

Redis初识~List命令

1112
来自专栏有趣的django

python面试题(持续更新)

第1~10题 1、一行代码实现1--100之和 >>> sum(range(1,101)) 5050 >>> 2、如何在一个函数内部修改全局变量 a= 3 ...

43711
来自专栏Java帮帮-微信公众号-技术文章全总结

Java读写Properties属性文件公用方法

Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配...

1222

扫码关注云+社区

领取腾讯云代金券