【问题标题】:In Kotlin, how do you declare a data class with zero constructor parameters?在 Kotlin 中,如何声明一个构造函数参数为零的数据类?
【发布时间】:2017-09-11 09:38:49
【问题描述】:

假设我想为整数列表声明一个简单的代数数据类型:

sealed class IntList
data class Cons(val head: Int, val tail: IntList): IntList()
data class Nil() : IntList()

但是,最后的声明导致错误

数据类必须至少有一个主要的构造函数参数

  1. 为什么会出现这种限制?查看文档,似乎没有很好的技术理由要求数据类构造函数是非空的。
  2. 是否可以在不必编写大量样板代码的情况下表达空构造函数?如果我将最后一个声明更改为类似

    sealed class Nil() : IntList()
    

    然后我失去了 hashCode()equals() 的免费实现,这些实现是通过 data class 声明免费提供的。

编辑

Alex Filatov 在下面给出了一个很好的简短解决方案。显然,Nil 的实例永远不会超过一个,所以我们可以只定义一个单例对象

object Nil : IntList()

但是,如果我们的列表由类型参数参数化,我们会怎么做?也就是说,现在我们定义的前两行将是

sealed class List<A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()

我们不能为任何A 声明派生自List&lt;A&gt; 的多态单例Nil 对象,因为我们必须在声明时为A 提供具体类型。解决方案(取自this post)是将A声明为协变类型参数,并将Nil声明为List&lt;Nothing&gt;的子类型,如下所示:

sealed class List<out A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()
object Nil : List<Nothing>()

这让我们可以写

val xs: List<Int> = Cons(1, Cons(2, Nil))
val ys: List<Char> = Cons('a', Cons('b', Nil))

【问题讨论】:

  • Related: stackoverflow.com/questions/37873995/… 不过好像不适合你的情况。
  • 另外,“请注意,未在主构造函数中声明的属性不参与相等性检查和哈希码计算。
  • @UlrikRasmussen 如果类不应包含任何字段,为什么需要 hashCode()equals()
  • 如果我想比较两个列表。但这只是在存在 Nil 的不同实例时才会出现的问题。通过将 Nil 表示为单例,这些方法的默认实现就足够了
  • @UlrikRasmussen 请发布您的编辑作为答案! :) 答案不应该出现在问题中

标签: kotlin


【解决方案1】:

因为没有数据的data class 没有意义。对单身人士使用object

object Nil : IntList()

【讨论】:

  • 这适用于我的用例,它是一个没有类型参数的简单代数数据类型。但是,我将如何为参数化类型表示空值构造函数?例如,让我们用 cons 构造函数 data class Cons&lt;A&gt;(val h:A, val t:List&lt;A&gt;): List&lt;A&gt;() 泛化到 sealed class List&lt;A&gt;。我不能声明多态对象object Nil&lt;A&gt; : List&lt;A&gt;()
  • 我找到了解决方案并相应地更新了问题
【解决方案2】:

你必须创建一个普通的类

class Nil : IntList()

并自己实现hashCode()equals()

没有字段的数据类没有任何意义,因为它的工作是表示数据。


或者:您可以使用作为单个实例类的对象类(如Alex Filatov 所说)。由于您不需要为每个 Nil 实例指定一个状态,因此它们可以共享一个。

【讨论】:

    【解决方案3】:

    如果您真的希望源代码中的一致性,您可以将默认值用于可能的最小数据类型。

    data class Nil(val _u: Byte = 0) : IntList()
    

    data class Nil(val _u: Nothing? = null) : IntList()
    

    【讨论】:

      猜你喜欢
      • 2011-10-12
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多