数据类(Data Classes)
我们常常创建仅仅持有数据的类,类似Java中的POJO或JavaBean,其对象我们一般称为实体(entity),因此它对应我们常说的Entity类。在一般UI应用分层架构中,例如MVC,MVP,MVVM等,都含有一个模型(Model)层,实体类型就属于这一块,它是构建业务的基石。
为此Kotlin专门定义了data类型:
data class User(val name: String, val age: Int)
编译器会根据主构造函数中声明的属性自动生成如下成员:
- equals()/hashCode()对
- toString()方法,返回字符串形式为"User(name=John, age=42)"
- componentN() 方法,其中N对应于属性声明的顺序
- copy()函数
为了保持生成代码的一致性和行为的有效性,data类必须满足以下要求:
- 主构造器需要至少一个参数
- 所有主构造器参数需要声明为val或var
- Data类型不能是abstruct、open、sealed或inner的
此外,对于成员继承,成员生成遵循以下规则:
- 如果一个data类正文中明确实现了equals(),hashCode(),toString()方法,或者超类中有final修饰的实现,那么这些方法便不会生成,直接使用已有的实现。
- 如果超类有open修饰的componentN()方法并且返回兼容的类型,那么对应的生成方法会重写超类的方法,否则会报错。
- 显式地实现componentN()和copy()是不允许的
在JVM中,如果生成类需要有一个无参构造器,所有属性的默认值必须明确指定。
data class User(val name: String = "", val age: Int = 0)
拷贝
copy()方法有什么用?有时我们需要拷贝一个对象,同时改变它的某些属性,并保持其它属性不变,使用copy()方法就可以了,其实现类似这样:
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
对象的属性值作为copy的默认参数值,我们可以传递希望改变的值,而保留其它值不变:
val jack = User(name = "Jack", age = 2)
val newJack = jack.copy(name = "New Java")
结构声明(Destructuring Declarations)
生成的component方法可以使它们使用解构声明中:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
标准库Data类
标准库提供了两个Data类:Pair
和Triple
。
枚举类型(Enum Classes)
枚举类型最常见的基本使用是实现类型安全的枚举:
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
每个枚举常量都是一个对象,枚举常量使用逗号分开。
初始化
由于每个枚举常量都是一个实例,可以这样初始化:
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}