Kotlin数据类主构造函数中的本地参数

8
关于data类,禁止在主构造函数中不使用varval关键字,即每个参数都会被隐式转换为类属性。然而,有时我不希望每个参数都被转换为类属性。

因此,据我所知,在主构造函数中没有办法传递一个仅在构造函数内部可访问且在实例构建后被遗忘的参数。这样做有好的原因吗?

我唯一能想到的解决方法是,不使用data类或使用允许使用非var/val前缀变量的辅助构造函数。然而,如果有很多需要传递的参数,那么使用辅助构造函数会极大地增加类的体积。当然,我可以将所有参数封装到另一个对象中,但那只是将问题转移到了另一个地方。

是否有推荐的方法或模式来应对这种情况?

2个回答

6
你并没有受到任何限制,只需要以稍微不同的方式进行操作。
数据类旨在非常清晰地说明它们包含什么以及以什么顺序,只允许成员位于主构造函数参数列表中。
但你有其他选择:使用次要构造函数和/或创建与类名相同但重载不同的顶级函数,或在伴生对象中创建工厂方法。
data class Person(val name: String, val age: Int) {
    // secondary constructor
    constructor (name: String): this(name, 0) {
       // ... make a newborn
    }

    // factory methods in companion object
    companion object {
        fun of(name: String, birthdate: LocalDate): Person {
            return Person(name, yearsSince(birthdate))
        }
    }
}

// function with same name as class acting like a constructor
fun Person(name: String, birthdate: LocalDate): Person {
    return Person(name, yearsSince(birthdate))
}

// these all work now:

Person("Fred", 30)                                  // primary constructor
Person("Baby")                                      // secondary constructor
Person("Geoff", LocalDate.parse("12/08/1990"))      // top-level function
Person.of("Jennifer", LocalDate.parse("01/01/1981") // companion function

您也可以通过将其设置为私有来隐藏主构造函数,但您无法隐藏该构造函数的copy版本。

顺便说一下,使用此合同具有主构造函数的数据类确实有助于序列化/反序列化库知道如何处理否则可能是猜测的类。这是一件好事!


非常感谢你提供这些详细的示例。 - Jan B.

0

首先,我必须说的是这是我的个人意见,所以请谨慎对待。

来自官方 Kotlin 文档

我们经常创建主要用于保存数据的类。在这样的类中,一些标准功能和实用函数通常可以从数据中机械地派生出来。

因此,data classes 应该被用作数据持有者,并且它们不应该包含太多逻辑。

从我的角度来看,当您想要将某些东西传递给构造函数但类不存储该数据时,可能与此相关的某些逻辑。

常见情况是:

  1. 使用某个标志来更改构造函数的行为

  2. 传递一些包装所有所需数据的类,然后将其提取到每个单独的字段中。

在第一种情况下,我们清楚地看到这不是 data class 的用例之一。

而第二种情况则是糟糕的代码,它引入了不必要的依赖关系,并隐藏了该类实际需要的内容。

构造函数应该简单,它们接收类所需的数据并将其绑定到字段,不应该在那里放置太多逻辑。准备所有数据应该由使用构造函数的人来完成,如果在创建新实例时存在一些可重复的代码,则可以考虑使用“工厂方法”来封装它。

谢谢。非常有趣的见解。有第三种情况,您需要将对象传递给超类构造函数。我们最近在另一篇文章中讨论过这个问题:https://dev59.com/p63la4cB1Zd3GeqPJjw1。我喜欢你使用工厂方法的建议。 - Jan B.
1
哦,没错,还有那种情况,但是我之前提到的覆盖方法已经解决了这个问题。数据类的行为有点奇怪,因为它们只用于简单的数据容器,正如它们的名字所示。如果需要一些逻辑处理,总是可以使用普通的 - FilipRistic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接