在Kotlin中,如何使用零构造函数参数声明数据类?

Ulr*_*sen 9 kotlin

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

sealed class IntList
data class Cons(val head: Int, val tail: IntList): IntList()
data class Nil() : IntList()
Run Code Online (Sandbox Code Playgroud)

但是,最后一个声明会导致错误

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

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

    sealed class Nil() : IntList()
    
    Run Code Online (Sandbox Code Playgroud)

    然后我失去了免费的实现hashCode()equals()免费data class声明.

编辑

Alex Filatov给出了一个很好的简短解决方案.显然,您永远不需要多个实例Nil,因此我们可以只定义一个单例对象

object Nil : IntList()
Run Code Online (Sandbox Code Playgroud)

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

sealed class List<A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()
Run Code Online (Sandbox Code Playgroud)

我们不能声明NilList<A>any 派生的多态单例对象A,因为我们必须A在声明时提供具体类型.解决方案(取自这篇文章)是声明A为协变类型参数并声明为如下Nil的子类型List<Nothing>:

sealed class List<out A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()
object Nil : List<Nothing>()
Run Code Online (Sandbox Code Playgroud)

这允许我们写

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

小智 14

因为data class没有数据没有意义.使用object的单身:

object Nil : IntList()
Run Code Online (Sandbox Code Playgroud)