具有不在构造函数中的附加属性的 Kotlin 数据 class

Kotlin data class with additional properties not in constructor

开始使用 Kotlin,想做一个数据class

data class Person(val Email: String, val firstName: String, val lastName: String)

但是假设我想添加我在使用构造函数时不知道的其他属性,但我想在以后知道时存储这些数据,例如一个人的心情(表示为字符串)

在Java中,我会制作这样的数据class。我将能够不将它包含在构造函数中,并制作一个 getter 我可以在以后设置它的地方。

public class Person{

     private String email;
     private String firstName;
     private String lastName;
     private String mood;

     public person (String email, String firstName, String lastName){
      this.email = email;
      this.firstName = firstName;
      this.lastName = lastName;
    } 

    public setMood(String mood){
     this.mood = mood;
    }
}

Kotlin 似乎对此没有答案,或者如果有我不知道如何正确表达。因此,为什么这个问题已经可以回答,但我找不到它。

我明白,如果不在数据 class 行中包含心情,Kotlin 可能无法将心情识别为数据的一部分 class 但除了将其包含在构造函数和设置中之外它为 null 我不确定还能做什么,或者这是我应该做的吗?

您应该可以将其作为 属性 添加到 Person。在 Kotlin 中,数据 class 仍然是 class,它只是带有一些额外的东西(toString、复制构造函数、hashCode/equals 等)。您仍然可以定义任何您想要的属性。

data class Person(val Email: String, val firstName: String, val lastName: String) {
    var mood: String? = null
}

在这种情况下,它可以为 null,因为正如您所说,您可能要到后来才能知道心情。

Kotlin 的数据 class 必须 有第一个构造函数,你可以通过不使用 data 关键字来避免它。

如果您仍想向数据 class 添加另一个 属性,您可以执行以下操作:

data class Person(val email: String, val firstName: String, val lastName: String){
    var mood: String = ""
}

通过这种方式,您可以 person.mood = "happy" 而无需将其包含在构造函数中。

Kotlin 仅在为您提供 Data class 提供的 "for free" 功能时考虑传递给主构造函数的值。除此之外,您可以添加您想要的任何其他属性,但在 Kotlin 通过您将 class 标记为 data.

编写的特殊代码中没有考虑到它们

根据 Kotlin 文档:

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:

据此,在主构造函数之外声明属性实际上有好处。您也许可以通过主构造函数声明一个 属性,但选择不这样做。

你不仅要提供一个主构造函数,而且还必须包含至少一个 属性 声明。如果您不这样做,那么将 class 设为 data class 将没有任何好处。但是标记 class 不会限制您可以用它做的其他事情 class.

你试过了吗:

data class Person(val Email: String, val firstName: String, val lastName: String) {
    var mood: String? = null
}

@Todd 和@jingx 的答案的替代方法是

data class Person(val Email: String, val firstName: String, val lastName: String, var mood: String? = null)

不同的是,这种方式mood参与了toString/equals/hashCode/copy,而你可以 在构造函数调用中设置 mood。即使对于这种特定情况可能不希望这样做,但它在其他情况下可能会有用。