在Kotlin中,如何用零构造函数参数声明一个数据类?
假设我想为整数列表声明一个简单的代数数据类型:
sealed class IntList data class Cons(val head: Int, val tail: IntList): IntList() data class Nil() : IntList()
但是,最后的声明会导致错误
数据类必须至少有一个主构造函数参数
- 为什么这个限制存在? 查看文档,似乎没有好的技术理由要求数据类构造函数是非空的。
-
是否有可能表达无用的构造函数,而不必写大量的样板代码? 如果我把最后一个声明改成类似的东西
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<A>
派生的多态Singleton Nil
对象,因为我们必须在声明时为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>()
这让我们写
val xs: List<Int> = Cons(1, Cons(2, Nil)) val ys: List<Char> = Cons('a', Cons('b', Nil))
因为没有数据的data class
没有意义。 使用object
的单身人士:
object Nil : IntList()
你将不得不创建一个平常的课程
class Nil : IntList()
并自己实现hashCode()
和equals()
。
没有字段的数据类没有任何意义,因为它的工作是表示数据。
或者:您可以使用一个对象类(如Alex Filatov所说),这是一个单一的实例类。 因为你不需要每个Nil
实例的状态,他们可以共享一个。
如果你真的想要你的源代码统一,你可以使用默认值的最小数据类型。
data class Nil(val _u: Byte = 0) : IntList()
要么
data class Nil(val _u: Nothing? = null) : IntList()