Android-Daily-Interview icon indicating copy to clipboard operation
Android-Daily-Interview copied to clipboard

2019-07-19:谈谈你对Kotlin中的 data 关键字的理解?相比于普通类有哪些特点?

Open Moosphan opened this issue 4 years ago • 7 comments

Moosphan avatar Jul 19 '19 01:07 Moosphan

Data Classes

We frequently create classes whose main purpose is to hold data. In such a class some standard functionality and utility functions are often mechanically derivable from the data. In Kotlin, this is called a data class and is marked as data:

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

The compiler automatically derives the following members from all properties declared in the primary constructor:

  • equals()/hashCode() pair;
  • toString() of the form "User(name=John, age=42)";
  • componentN() functions corresponding to the properties in their order of declaration;
  • copy() function (see below).

To ensure consistency and meaningful behavior of the generated code, data classes have to fulfill the following requirements:

  • The primary constructor needs to have at least one parameter;
  • All primary constructor parameters need to be marked as val or var;
  • Data classes cannot be abstract, open, sealed or inner;
  • (before 1.1) Data classes may only implement interfaces.

Additionally, the members generation follows these rules with regard to the members inheritance:

  • If there are explicit implementations of equals(), hashCode() or toString() in the data class body or final{: .keyword } implementations in a superclass, then these functions are not generated, and the existing implementations are used;
  • If a supertype has the componentN() functions that are open{: .keyword } and return compatible types, the corresponding functions are generated for the data class and override those of the supertype. If the functions of the supertype cannot be overridden due to incompatible signatures or being final, an error is reported;
  • Deriving a data class from a type that already has a copy(...) function with a matching signature is deprecated in Kotlin 1.2 and is prohibited in Kotlin 1.3.
  • Providing explicit implementations for the componentN() and copy() functions is not allowed.

Since 1.1, data classes may extend other classes (see Sealed classes for examples).

On the JVM, if the generated class needs to have a parameterless constructor, default values for all properties have to be specified (see Constructors).

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

Properties Declared in the Class Body

Note that the compiler only uses the properties defined inside the primary constructor for the automatically generated functions. To exclude a property from the generated implementations, declare it inside the class body:

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

Only the property name will be used inside the toString(), equals(), hashCode(), and copy() implementations, and there will only be one component function component1(). While two Person objects can have different ages, they will be treated as equal.

data class Person(val name: String) {
    var age: Int = 0
}
fun main() {
//sampleStart
    val person1 = Person("John")
    val person2 = Person("John")
    person1.age = 10
    person2.age = 20
//sampleEnd
    println("person1 == person2: ${person1 == person2}")
    println("person1 with age ${person1.age}: ${person1}")
    println("person2 with age ${person2.age}: ${person2}")
}

Copying

It's often the case that we need to copy an object altering some of its properties, but keeping the rest unchanged. This is what copy() function is generated for. For the User class above, its implementation would be as follows:

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

This allows us to write:

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

Data Classes and Destructuring Declarations

Component functions generated for data classes enable their use in destructuring declarations:

val jane = User("Jane", 35) 
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"

Standard Data Classes

The standard library provides Pair and Triple. In most cases, though, named data classes are a better design choice, because they make the code more readable by providing meaningful names for properties.

yangkile avatar Jul 19 '19 01:07 yangkile

看头像表情 自古二楼出人才

yangfanggang avatar Jul 19 '19 08:07 yangfanggang

看头像表情 自古三楼出人才

Mrsunbw avatar Dec 20 '19 08:12 Mrsunbw

我觉得把,在没有对应的插件之前,大家还是使用 Java 的 bean 类把,做大数据的,使用 data 类,估计能累到吐血,纯属个人意见,如果有更好的,请提供下方法

Monkey-D-Vincent avatar Jul 22 '20 11:07 Monkey-D-Vincent

在Kotlin中,data关键字用于创建数据类(data class)。数据类是一种特殊类型的类,主要用于存储和传递数据。与普通类相比,数据类具有以下几个特点:

  1. 自动生成一些标准方法:当我们使用data关键字声明一个类时,Kotlin会自动生成一些标准方法,包括equals()hashCode()toString()copy()等。这些方法会根据类的属性自动生成相应的实现代码,方便我们进行对象的比较、复制和打印等操作。

  2. 自动解构功能:数据类允许我们使用解构声明(destructuring declaration)来将对象的属性分解为多个变量。这在某些情况下可以让代码更加简洁和可读。

  3. 对象复制:数据类提供了一个copy()方法,用于创建对象的副本并可以修改其中的属性值。通过复制对象,我们可以方便地创建新的对象,同时修改一些属性的值,而其他属性保持不变。

  4. 自动生成的componentN()方法:对于每个在主构造函数中声明的属性,数据类会自动生成对应的componentN()方法,用于按照属性的顺序获取属性值。这在一些特定的场景下,如使用集合的map()函数时,可以方便地获取对象的属性值。

需要注意的是,数据类有一些限制和要求,比如主构造函数至少有一个参数,且所有参数必须用valvar声明为属性。此外,数据类不能是抽象、密封(sealed)或内部类,并且不能继承其他类(但可以实现接口)。

总的来说,Kotlin中的数据类为我们处理数据提供了很多便利,减少了我们编写重复的代码,增加了代码的可读性和可维护性。

junbujian007 avatar Jul 17 '23 06:07 junbujian007

这是来自QQ邮箱的假期自动回复邮件。  

luckilyyg avatar Jul 17 '23 06:07 luckilyyg

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

Empty0Qc avatar Jul 17 '23 06:07 Empty0Qc