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

数据类和封闭类是Kotlin中的两种特殊的类,今天一起了解一下。更多精彩内容也可以关注我的微信公众号——Android机动车

数据类

数据类是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机动车

这里写图片描述

你可能感兴趣的:(转向Kotlin——数据类和封闭类)