Kotlin数据类的主要构造函数中的局部参数

时间:2018-07-29 13:17:29

标签: constructor kotlin data-class

关于data类,禁止在主要构造函数中使用varval关键字,即 every 被隐式地转换为类属性。但是,有时在某些情况下,我不希望每个参数都变成类属性。

据我所知,没有机会在主构造函数中传递参数,该参数只能在构造函数内访问,并且在实例构造完成后会被遗忘。有充分的理由吗?

我想解决这个问题的唯一方法是使用data类或使用允许使用非var / val前缀变量的辅助构造函数。但是,由于需要传递大量参数,因此辅助构造函数将极大地膨胀该类。当然,我可以将所有参数包装到另一个对象中,但这只会将问题转移到另一个地方。

是否有建议的方法或模式来应对?

2 个答案:

答案 0 :(得分:2)

您完全不受限制,您只需要做一些不同的事情即可。

数据类旨在非常清楚它们包含的内容和顺序,并且仅允许主要构造函数参数列表中的成员。

但是您还有其他选择:使用次要构造函数,和/或创建顶级函数,其名称与具有不同重载的类的名称相同,或者创建<伴侣对象中的strong>工厂方法:

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版本。

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

答案 1 :(得分:0)

我必须要说的第一句话是这是我个人的观点,因此请与盐同食。

来自官方科特琳documentation

  

我们经常创建主要目的是保存数据的类。在此类中,通常可以从数据中机械地得出一些标准功能和实用功能。

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

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

常见的情况是:

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

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

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

第二种情况只是错误的代码,它引入了对另一个类的不必要依赖,并隐藏了该类实际需要的东西。

构造函数应该简单,它们接收类所需的数据并将其绑定到字段,其中不应包含太多逻辑,应该由使用构造函数来准备所有数据的那些逻辑决定,并且在创建时是否存在一些可重复的代码新实例,那么最好使用factory method进行封装。