Kotlin学习之类与对象篇—数据类

我们会经常创建一些只用来保存数据的类。在这种类中一些标准功能和效用的函数通常可以根据数据机械地推导出来。在Kotlin中,它被称作数据类,并被标记为data:

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

编译器会根据主构造函数中所声明的所有属性自动推导出下列成员:

  • equls() / hashcode()
  • 打印"User(name=John, age=42)" 格式的 toString()方法
  • componentN(.)函数按声明顺序对应于所有属性
  • copy()函数

其中componentN(.)函数会在后面的章节详细讲解,这里暂时不管

为了确保生成的代码的一致性和有意义的行为,数据类必须满足以下要求:

  • 主构造函数至少有一个参数
  • 所有主构造函数的参数必须用valvar标记
  • 数据类不能为abstractopensealedinner
  • (Kotlin 1.1之前)数据类只能实现接口

此外,成员的生成遵循成员继承的一些规则:

  • 如果数据类中已经显示实现了equals(),hashCode() 或 toString() 方法,或者在其父类中已经final实现了这些方法,那么已实现的方法将不会再生成,而是使用已实现的方法
  • 如果超类型具有 opencomponentN() 函数并且返回兼容的类型, 那么会为数据类生成相应的函数,并覆盖超类的实现。如果超类型的这些函数由于签名不兼容或者是 final 而导致无法覆盖,那么会报错;
  • componentN()copy() 方法不支持显示实现

从Kotlin 1.1起,数据类可以继承其它类

在JVM平台上,如果生成的类需要无参构造函数,所有属性都要指定默认值。

data class User(val name: String = "", val age: Int = 0)

在类体中声明的属性

注意编译器只会为主构造函数中的属性自动生成函数,在类体中声明的属性将被排除在外。

data class Person(val name: String) {
    var age: Int = 0
}

上面这个Person类,只有属性name会被使用在toString()equals()hashCode()copy() 的实现中,并且只会有一个component函数component1()。当两个Person对象的age值不同时,它们仍然是equal的,因为默认的equals()方法不会考虑age属性,只考虑主构造函数中的属性。

    @Test
    fun testEquals(): Unit {
        val person1 = Person("crx")
        val person2 = Person("crx")
        person1.age = 2
        person2.age = 6
        assertTrue(person1.equals(person2))
    }

上面的测试代码不会报错

复制

通常我们需要复制一个对象,只改变其某些属性,其它属性保持不变。copy()方法就是用来做这个的。对于上面的User类,其实现方法如下:

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

它允许我们这样写:

val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

数据类和解构声明

数据类生成的component函数允许它们使用解构声明。

val jane = User("Jane", 35)
val(name, age) = jane
print("$name, $age years of age")

会打印出:Jane, 35 years of age

解构声明将在后面的章节细讲

标准数据类

Kotlin标准库中提供了PairTriple方法。在大多数情况下,使用命名的数据类是更好的设计选择,因为提供有意义的名字和属性会让代码更具可读性。

Pair使用方法如下:

val(name, age) = Pair("Jane", 23)
print("$name, $age years of age")

打印结果和上面的代码一样。

Triple使用方法和Pair相似,接收三个参数。

猜你喜欢

转载自blog.csdn.net/chenrenxiang/article/details/80988921