当前位置: 首页 > 知识库问答 >
问题:

如何为具有许多不可变属性的 Kotlin 数据类创建生成器

米裕
2023-03-14

我有一个静态编程语言数据类,我正在用许多不可变属性构建它,这些属性是从单独的SQL查询中获取的。如果我想使用构建器模式构建数据类,如何在不使这些属性可变的情况下做到这一点?

例如,而不是通过构造

var data = MyData(val1, val2, val3)

我想用

builder.someVal(val1)
// compute val2
builder.someOtherVal(val2)
// ... 
var data = builder.build()

同时仍然使用Kotlin的数据类特性和不可变属性。

共有3个答案

夏俊人
2023-03-14

无需在静态编程语言中创建自定义构建器-为了实现类似构建器的语义学,您可以利用复制方法-它非常适合您想要通过少量更改获得对象副本的情况。

data class MyData(val val1: String? = null, val val2: String? = null, val val3: String? = null)

val temp = MyData()
  .copy(val1 = "1")
  .copy(val2 = "2")
  .copy(val3 = "3")

或:

val empty = MyData()
val with1 = empty.copy(val1 = "1")
val with2 = with1.copy(val2 = "2")
val with3 = with2.copy(val3 = "3")

由于您希望一切都是不可变的,因此复制必须在每个阶段进行。

此外,只要生成器生成的结果是不可变的,在生成器中具有可变属性也可以。

臧令
2023-03-14

我认为科特林没有原生建筑商。您始终可以计算所有值并在末尾创建对象。

如果你仍然想使用构建器,你必须自己实现它。检查这个问题

冯玮
2023-03-14

我同意Grzegorz答案中的数据复制块,但它本质上与使用构造函数创建数据类的语法相同。如果您想使用这种方法并保持所有内容清晰易读,您可能会事先计算所有内容并最终将所有值一起传递。

要拥有更像构建器的东西,您可以考虑以下几点:

假设您的数据类是

data class Data(val text: String, val number: Int, val time: Long)

您可以像这样创建可变构建器版本,并使用构建方法来创建数据类:

class Builder {
    var text = "hello"
    var number = 2
    var time = System.currentTimeMillis()

    internal fun build()
            = Data(text, number, time)

}

以及像这样的构建器方法:

fun createData(action: Builder.() -> Unit): Data {
    val builder = Builder()
    builder.action()
    return builder.build()
}

Action是一个函数,您可以从中直接修改值,createData将在之后直接为您将其构建为数据类。这样,您可以使用以下方式创建数据类:

val data: Data = createData {
    //execute stuff here
    text = "new text"
    //calculate number
    number = -1
    //calculate time
    time = 222L
}

比方说,没有setter方法,但是您可以用新值直接给可变变量赋值,并在构建器中调用其他方法。

您还可以通过为每个变量指定自己的函数来利用 kotlin 的 get 和 set,这样它就可以做更多的事情,而不仅仅是设置字段。

也不需要返回当前的构建器类,因为您始终可以访问它的变量。

附加说明:如果您愿意,createData可以缩短为:

fun createData(action: Builder.() -> Unit): Data = with(Builder()) { action(); build() }.

“有了新的建设者,应用我们的行动并构建”

 类似资料:
  • 我们知道,要创建不可变类,我们需要将一个类声明为final,需要将所有字段声明为final,并且该类中不应该存在任何setter方法。我们需要在构造函数中初始化那些字段。 但是当我们有10多个字段或者更多字段的时候会发生什么呢?我们不能传递构造函数中的所有字段,对吧?在这个场景中,我们如何创建一个不可变的类呢?

  • 我想在Kotlin中为具有不可变属性的类型使用类型安全生成器。 我想到了两种解决方案: 选项 1:创建生成器类: 选项2:创建自定义委托以防止再次设置该值: 选项1的缺点是我必须维护两个类,选项2的缺点是编译器将允许再次设置< code>DataClass中的值,并且检查将只在运行时进行。 有没有更好的方法来解决这个问题而没有提到的缺点?

  • 我试图学习数组对象在Java但不明白。我确实明白如何将输入存储到数组对象中,但不明白如何比较数组中的每个项来做#7和#8。我试图在网上搜索,但从那里卡住了。 > 创建具有以下属性的班级学生:姓名、年龄、地址、电子邮件地址 创建一个空构造函数,用于初始化所有属性的空值。 创建一个接受所有参数并初始化所有属性的构造函数。 为所有属性创建访问器和变异器方法。 创建一个toString方法以返回学生的详细

  • 问题内容: 情况: 我有一个带有字段的类,因此它们不在构造函数中: 我想拥有一个包含所有字段的方法,并且不想手动编写它,以避免锅炉打印。在Java中,我将使用 Lombok 注释解决此问题。 题: 有什么方法可以在Kotlin中实施吗? 问题答案: 推荐的方法是手动编写(或由IDE生成),并希望您没有太多这样的类。 目的是为了适应最常见的85%的情况,而剩下15%留给其他解决方案。

  • 我对Kotlin很陌生,并试图将一个项目从Java迁移到它。我对Kotlin的属性和它们的getters/setter以及可见性范围有点困惑。 我想要实现的是: 所以基本上我需要创建一个具有私有属性的类。此属性应由公共 getter 访问,但它不应具有 setter。此外,此属性应该是内部可变的,以便可以使用某种方法(如 更改其值。 据我所知,我不能将其声明为,因为在这种情况下,它将是完全不可变的

  • Kotlin有一个const关键字。但我不认为kotlin中的常数是我所认为的。这似乎与C中的const非常不同。在我看来,its仅适用于静态成员和Java中的原语,不针对类变量进行编译: 由于这似乎不起作用,我认为我真正想要的是第二个类,它删除我不想支持的操作: 这种方法的明显缺点是,我不能忘记更改这个类,以防我更改,这对我来说非常危险。 但是我不确定如何做到这一点。所以问题是:如何用意识形态静